官方文档地址:https://router.vuejs.org/zh-cn/advanced/navigation-guards.html
全局守卫
可以使用 router.beforeEach
注册一个全局前置守卫:
例如: 判断在用户未登录时, 跳转到 "/login" 的路由, 登录时,直接跳转到默认路由
const router = new VueRouter({ ... }) // 实例化 router
router.beforeEach((to, from, next) => { console.log(to); // 即将进入的路由 console.log(from); // 即将离开的路由(当前路由) let token = window.sessionStorage.getItem("token") if( token){ to.path === "/login" ? next({ path: ‘/‘ }) : next(); }else { to.path !== "/login" ? next("/login") : next() ; } })
下面是官方文档对于参数说明:
每个守卫方法接收三个参数:
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。
全局解析守卫
在 2.5.0+ 你可以用 router.beforeResolve
注册一个全局守卫。这和 router.beforeEach
类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
路由独享的守卫
在路由配置中属性 beforeEnter
const router = new Router({ mode:‘history‘, routes: [ { path: ‘/‘, name: ‘home‘, component: Home }, { path: ‘/test‘, name: ‘test‘, component: () => import("@/view/test"), beforeEnter: (to, from, next) => { console.log(‘独享的守卫‘); next(); } } ] }) router.beforeEach((to, from, next) => { console.log("全局守卫"); next(); })
同时存在全局守卫和再执行路由独立守卫时,执行的结果是:
先执行全局守卫,再执行路由独立守卫。
组件内的守卫
可以在组件内部使用路由导航守卫, (我的理解类似于路由的生命周期)。
beforeRouteEnter
路由组件被渲染之前之前调用, 注: 此时不能获取到组件实例的this
beforeRouteUpdate(2.2新增)
路由被修改是调beforeRouteLeave
导航离开该组件的对应路由时调用
1. 守卫 beforeRouteEnter
export default { data(){ return { txt:‘白夜行将‘ } }, beforeRouteEnter (to, from, next) { console.log(this); console.log(this.txt); //需要执行 执行next()函数, 否则不会渲染 next(); } }
上面的代码执行的结果如下:
可以得出 :
beforeRouteEnter
守卫不能访问 this
,因为此时新组件还未被创建;
如果需要对组件实例进行操作, 可以在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。即: 用next()的回调函数进行操作实例
beforeRouteEnter (to, from, next) { next( scope =>{ console.log(scope.txt); scope.txt = "暗夜来迟" console.log(scope.txt); } ) }
注意: 只有beforeRouteEnter
支持给 next
传递回调的唯一守卫; beforeRouteUpdate
和 beforeRouteLeave 此时组件以及完成创建, this 已经可以使用。
2. 守卫 beforeRouteUpdate
在当前路由改变,但是该组件被复用时调用
举例来说,对于一个带有动态参数的路径 /test/:id,在 /test/1 和 /test/2 之间跳转的时候,
在 路由hash模式时,
渲染同样的 test 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用
可以访问组件实例 this
beforeRouteUpdate (to, from, next){ console.log(this.txt); next(); },
在变化id时, 会调用 beforeRouteUpdate 钩子
注意: 使用该守卫时, 路由的模式只能是hash, 使用history模式, 该守卫不生效,
3. 守卫 beforeRouteLeave
离开该组件的对应路由时调用,此时还可以访问组件 this;
用户操作未完成是,不允许退出时,可以是next(false); 阻止导航切换
beforeRouteLeave (to, from , next) { next(false) },
完整的导航解析流程
在router 的index 文件中设置
beforeEach beforeResolve afterEach 和 路由独享守卫 四种守卫;
index
在路由home文件配置 beforeRouteLeave 路由
beforeRouteLeave (to, from , next) { console.log(‘路由home的守卫 beforeRouteLeave‘); next() }, deactivated(){ console.log(‘home离开‘); },
home
在路由test文件配置 beforeRouteEnter路由
beforeRouteEnter (to, from, next) { console.log(‘路由test的 beforeRouteEnter 守卫‘); next(scope => { console.log(‘beforeRouteEnter 守卫 回调函数‘); }) }, beforeRouteLeave (to, from , next) { console.log(‘路由test的 beforeRouteLeave 守卫‘); next(false) }, activated(){ console.log(‘test,完成加载‘); }
test
控制台打印结果 (keepa-alive 组件切换)
在点击路由跳转按钮后,执行顺序
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 守卫。
- 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫 (2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 执行 路由home 的 keep-alive 的 deactivated 钩子
- 触发 DOM 更新 ,执行路由test 的 keep-alive 的 activated 的钩子
- 用创建好的实例调用
beforeRouteEnter
守卫中传给next
的回调函数。
以上个人学习理解,如有错误请指正
原文地址:https://www.cnblogs.com/blog-sanyu/p/10151143.html