1.整体思路
- 路由保护的策略
- 日常开发如何应用
- 底层的实现逻辑
2.所有钩子函数
2.1.全局的钩子函数
2.1.1beforeEach(to,from,next) 路由改变前调用
常用验证用户权限
beforeEach ()参数
to :即将要进入的目标路由对象
from:当前正要离开的路由对象
next:路由控制参数
next():如果一切正常,则调用这个方法进入下一个钩子
next(false):取消导航(即路由不发生改变)
next('/login'):当前导航被中断,然后进行一个新的导航
next(error):如果一个Error实例,则导航会被终止且该错误会被传递给router.onError() afterEach (to,from) 路由改变后的钩子
router.beforeEach((to, from, next) => {
console.log(to.fullPath);
if(to.fullPath!='/login'){//如果不是登录组件
if(!localStorage.getItem("username")){//如果没有登录,就先进入login组件 进行登录
next('/login');
}else{//如果登录了,那就继续
next();
}
}else{//如果是登录组件,那就继续。
next();
}
})
2.1.2 beforeResolve(to,from,next)
2.1.3 afterEach(to,from)
2.2路由配置中的导航钩子
beforeEnter (to,from,next)
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => { // ...
},
beforeEnter: (route) => {
// ...
}
}
]
});
2.3.组件内的钩子函数
2.3.1. beforeRouteEnter(to,from,next)
该组件的对应路由被comfirm前调用。 此时实例还没被创建,所以不能获取实例(this)
2.3.2. beforeRouteUpdate(to,from,next)
当前路由改变,但改组件被复用时候调用 该函数内可以访问组件实例(this)
2.3.3. beforeRouteLeave(to,from,next)
当导航离开组件的对应路由时调用。 该函数内可以访问获取组件实例(this)
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当钩子执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的 时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调
用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
3.完整的路由流程
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新(mounted)。
- 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
4.路由监测变化
监听到路由对象发生变化,从而对路由变化做出响应
const user = {
template:'<div></div>',
watch: {
'$route' (to,from){
// 对路由做出响应
// to , from 分别表示从哪跳转到哪,都是一个对象
// to.path ( 表示的是要跳转到的路由的地址 eg: /home ); }
}
}
// 多了一个watch,这会带来依赖追踪的内存开销,
// 修改
const user = {
template:'<div></div>',
watch: {
'$route.query.id' {
// 请求个人描述
},
'$route.query.page' { // 请求列表
}
}
}
6.总结:
- vue-router保护路由安全是通过导航守卫实现的。通过不同的导航钩子函数,在函数里判断是否有权限再做跳转实现全局或局部的保护指定路由的目的。
- 路由中的导航钩子有三种(从大到小) :全局 ,路由配置 ,组件。一般全局权限是用beforeEach(to ,from,next => {})来设置守卫。每次路由导航都会触发他,根据当前用户的登录状态,决定next()传入不同的参数,控制跳转不用的地址。next(false)不跳转,next(path)重定向新地址,next()正常跳转原设定的地址。
- 底层实现,通过hooks注册表,会注册记录所有声明的钩子hook,在router准时导航之前,会批量执行注册表的所有hook。并把目标to 和 来源from,以及后续的处理函数next传递给我们处理。
- VueRouter源码实现
- 实现 VueRouter插件类,包含install方法
- router-link和router-view组件标签,通过h渲染函数-动态生成a标签
- router.js路由配置表信息会统一维护到matchList 数组
- 如果是hash模式使用
hashchange事件监听url变化,如果是history模式是用popState监听url变化 - 把请求的path和matchList做匹配,找出要实例化的配置信息,使用h渲染函数进行实例化。