官方地址:https://router.vuejs.org/zh/guide/
官方文档中虽然有着正式介绍,但是真正在项目的使用方面确是比较模糊的。因此对其整理方便以后查阅。
基本使用
首先是安装:
npm install vue-router --save
如何引入
import Vue from 'vue' // 引入vue本身,一般main.js中已经存在
import VueRouter from 'vue-router' // 引入vue-router
Vue.use(VueRouter) // 使用vue-router
配置使用
一般情况下,项目中必定会有一个叫做router.js(名字各异)文件,这个文件中必然会存在以上的引入三句话,并且导出一个vue-router实例对象。且该文件必定会在main.js中引入并且注册在new Vue({})中,如:
main.js文件中:
这种引用在常规项目中都是大同小异的,有一个专门的文件进行引用注册并且导出一个项目vue-router实例(export default new Router(routerConfig)),然后在main.js中引用注入即可。
注意:
1.之后项目中所有的路由都是由router.js这个文件进行路由管理
如:比如我要在axios中引入路由并且进行一些页面跳转则是
import router from './router.js';
.....
router.push(...) // 这里直接跳转路由注册的路径即可
这里直接引router.js文件即可拿到vue-router实例
而不是再次引入vue-router本身
import Router from “vue-router”; // 这个只需要在router.js中引一次即可
2.关于路由配置项:配置路由
路由访问:通过访问路由路径实际访问到路由对应的组件,如:访问/test 则直接展示test.vue对应的组件内容
第一种路由的配置引入方式
const account = () => import('src/views/project-entrance/account/account'); // 命名
const loginComponent = () => import('src/views/project-entrance/account/login'); // 命名
{
path: '/account',
name: 'account',
component: account, // 引入
meta: {
requireAuth: false
},
redirect: '/account/login',
children: [{
path: '/account/login',
name: 'login',
component: loginComponent, // 引入
meta: {
requireAuth: false,
title: '登录'
}
}]
},
如图:
base表示基础路径,默认为’’,如果加上内容如:/test 那么所有的路由都将加上 /test 如: /account => /test/account
第二种路由的配置引入方式:
{
path: '/test',
name: 'test',
component: () => import('src/views/test/test.vue'), // 直接引入,不需要命名
children: [
{
path: '/test/echarts',
name: 'testEcharts',
component: () => import('src/views/test/echarts.vue') // 直接引入,不需要命名
}
]
}
**两种的配置方式本质是一样的,都是按需引用,即路由懒加载,区别仅仅是第一种能将所有的路径都放置在一起管理而已。访问方式如:以这种方式引入404,account模块路径,但只访问404模块路径,则只有404路径对应的组件加载,account路径对应的组件不会加载进来
**
第三种路由的配置引入方式:
import NotFound from "src/components/layout/404.vue";
{
path: "*",
name: "404",
component: NotFound,
meta: {
requireAuth: false,
title: '404'
}
},
这种方式则是直接引用,一旦进入,则所有引用的路由内容都会加载进来。如:以这种方式引入404,account模块路径,但只访问404路径,两者的路由路径对应的组件都会加载进来
注意事项:
- 重定向的概念: 当给/a路由定义了重定向路由/c时,访问/a路由,路由路径将会跳转到/c的路由处并且展示c组件的内容
- 别名的概念:假若/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a(即展示a组件的内容),就像用户访问 /a 一样
- 路由懒加载是当前常用的一种路由配置内容,即进入路由后根据路由的需要则只加载对应的组件,如:/account 则 只会加载到account对应的组件。引用方式为: () => import(’./Foo.vue’) 。
- const Foo = () => import(/* webpackChunkName: “group-foo” */ ‘./Foo.vue’) // 这种特殊的注释方式可以将内容打包在同个异步块中,这里为:'group-foo’块
- 某些时候可以使用组件内的watch方式监听路由变化,以适应一些需求如:
// 某个进入的组件内
watch: {
'$route' (to, from) {
// 根据需要可以获取当前路由的内容
console.log(to);
console.log(from);
}
}
最后需要注意的是要在对应的组件中配置:
有几层路径则嵌套几层
如:第一层 /account 则是 在app.vue中有:
account 下面还有一个children属性,因此访问account下的路由/account/login则需要在account组件中也配置
如:第二层 /account/login 则是在 account.vue中
路由跳转
在template的使用方式(声明式),使用router-link包裹需要跳转的内容即可
传递内容可以为一个字符串
<router-link to='account/login'> </router-link>
传递内容也可以为一个对象
<router-link :to='{path: 'account/login'}'> </router-link>
在script中的使用方式(编程式)
跳转方式:三种
router.push(…) 常用的跳转方式
router.replace(…) 与push类似,区别在于不会向 history 添加新记录,而是替换。
router.go(n);这种是为了前进/返回到某一个跳转过的页面(与push配合),如:
go跳转示例:
// 后退一步记录,等同于 history.back()
router.go(-1)
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
push跳转示例:
// 字符串
this.$router.push('home')
// 对象
this.$router.push({ path: 'home' })
// 命名的路由
this.$router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})
push带参跳转方式组合
通常使用组合是:
path + query (常用)
name + params
特殊情况特定。
跳转后参数获取方式:
// 在进入的路由对应的组件中的created()中获取
let que = this.$route.query.xx
let par = this.$route.params.xx
注:
1.params传递的参数一旦刷新页面即会消失
2.获取数据是$route 不是 $router
3.params 和 query区别与示例:
示例:
–params:(path配置id)/router1/:id => /router1/678 ,这里的id叫做params
–query:/router1?id=123 ,这里的id叫做query。
当你使用params方法传参的时候,要在路由后面加参数名,并且传参的时候,参数名要跟路由后面设置的参数名对应。使用query方法,就没有这种限制,直接在跳转里面用就可以。
注意:如果路由上面不写参数,也是可以传过去的,但不会在url上面显示出你的参数,并且当你跳到别的页面或者刷新页面的时候参数会丢失
区别:
–3.1、params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容
–3.2、params、query不设置也可以传参,但是params不设置的时候,刷新页面或者返回参数会丢失,query并不会出现这种情况
深入了解
1.history模式和hash模式
模式设置:默认为hash模式,通常情况下就用hash模式即可满足各种需求
这个配置与routes同级,可以配置为history或者hash两个内容,
两者的区别:就是路径格式的丑不丑问题。
hash模式:路由路径为 /#/…/…/之类的,路径样式非常丑,但是已经满足各种需求
history模式:路由路径可以定义为自己喜欢的格式
如:http://yoursite.com/user/id,这样就漂亮多了,但是页面刷新可能会出现一些问题,因此需要服务器配置一下路径,即刷新页面的时候要导航到index.html页面去
history的好处就是可以尽情的使用 Browser History APIs 的接口了
2.路由守卫
完整的导航解析流程:访问从/a路由$route.push()到/b路由再到b路由对应的组件展示完毕的整个路由过程
- 导航被触发。// a路由中触发$route.push()
- 在失活的组件里调用离开守卫。// a路由触发 beforeRouteLeave (to, from, next){}
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。// 新路由(没进入过)则不会调用
- 在路由配置里调用 beforeEnter。// b路由的路由配置中,开始进入b路由
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。// 开始进入b路由组件中
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。// b路由加载完毕
路由守卫分为全局守卫、路由独享守卫、组件内守卫三种守卫。
全局守卫有三种,需要导入router实例并且在其上注册,如本例中的router.js文件,然后使用
router.beforeEach((to, from, next) => {})
router.beforeResolve((to, from, next) => {})
router.afterEach((to, from, next) => {})
路由独享守卫有一种: 直接注册在路由的路径上与路径path平级参数如上
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
组件内守卫有三种:可以看作组件生命周期类似
<script>
export default {
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
};
</script>
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要调用 next 方法,否则钩子就不会被 resolved。
示例一:路由拦截配合元信息阻止进入非登录页面
示例二:路由从/account =>/login路径过程中,需要对某些特殊内容进行处理
示例三:路由从/account => /login路径过程中,需要通过调用接口获取到数据,然后才能组件生命周期的执行,否则组件跳转到另一个路由或者其他操作
3.路由原信息
路由元信息注册在每个路由的meta字段中,可以自定义字段名称,然后配置路由的各个守卫使用,直接通过to.meta.xx 或者 from.mata.xx即可获取到内容
4.命名视图(偶尔用)
命名视图就是给加上一个name属性而已
<router-view class="view three" name="b"></router-view>
一个视图可以理解为一个出口,当路由访问时候的组件放置位置,
命名视图可以理解为在一个组件中放置多个出口,即当访问某一个路由/test时候,我需要同时展示多个内容,左边为导航,右边为主内容。
(当然这种情况也可以通过组件的import形式导入从而做成三个组件同在一个组件中然后只注册一个路由和组件的情况,达到同样的效果,因此这个才用的比较少)
官方解释:
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default
<router-view class="view one"></router-view> // 默认视图
<router-view class="view two" name="a"></router-view> // a视图
<router-view class="view three" name="b"></router-view> // b视图
routes: [
{
path: '/test', // 访问test路径的时候
components: {
default: Foo, // 默认视图展示Foo组件
a: Bar, // a视图展示 Bar组件
b: Baz // b视图展示Baz组件
}
}
]
5.路由组件传参(不常用)
这里的传参与常规的路由参数传递有所不同,应用场所比较特殊。
https://router.vuejs.org/zh/guide/essentials/passing-props.html
6.过渡动效(不常用)
实质是:在外面或者组件外面包裹一层组件来实现一些切换效果。
官方地址:https://router.vuejs.org/zh/guide/advanced/transitions.html
7.滚动行为(不常用)
注意: 这个功能只在支持 history.pushState 的浏览器中可用
作用:设置当前页面的scoll滚动状态,例如:在路由切换之后总是滚动到顶部;保存当前的滚动状态,切换后仍然在当前滚动处;
官方地址:https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html