说到Vue的钩子函数,可能很多人只停留在一些很简单常用的钩子( created , mounted ),而且对于里面的区别,什么时候该用什么钩子,并没有仔细的去研究过,且Vue的生命周期在面试中也算是比较高频的考点,那么该如何回答这类问题,让人有眼前一亮的感觉呢...
Vue-Router导航守卫
有的时候,我们需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录页面让其登录。
为此我们有很多种方法可以植入路由的导航过程: 全局的, 单个路由独享的, 或者组件级的 , 推荐优先阅读官方路由文档
全局守卫
vue-router全局有三个守卫:
router.beforeEach 全局前置守卫 进入路由之前
router.beforeResolve 全局解析守卫(2.5.0+) 在beforeRouteEnter调用之后调用
router.afterEach 全局后置钩子 进入路由之后
使用方法:
// main.js 入口文件 import router from './router' ; // 引入路由 router . beforeEach (( to , from , next ) => { next (); }); router . beforeResolve (( to , from , next ) => { next (); }); router . afterEach (( to , from ) => { console . log ( 'afterEach 全局后置钩子' ); });
to,from,next 这三个参数:
to和from是 将要进入和将要离开的路由对象 ,路由对象指的是平时通过this.$route获取到的路由对象。
next:Function这个参数是个函数,且 必须调用,否则不能进入路由 (页面空白)。
next() 进入该路由。
next(false): 取消进入路由,url地址重置为from路由地址(也就是将要离开的路由地址)。
next 跳转新路由,当前的导航被中断,重新开始一个新的导航。
我们可以这样跳转:next('path地址') 或者 next({path:''}) 或者 next({name:''}) 且允许设置诸如 replace: true、name: 'home' 之类的选项 以及你用在router-link或router.push的对象选项。
路由独享守卫
如果你不想全局配置守卫的话,你可以为某些路由单独配置守卫:
const router = new VueRouter({ routes : [ { path : '/foo' , component : Foo , beforeEnter : ( to , from , next ) => { // ... } } ] })
路由组件内的守卫:
beforeRouteEnter 进入路由前
beforeRouteUpdate (2.2) 路由复用同一个组件时
beforeRouteLeave 离开当前路由时
文档中的介绍:
beforeRouteEnter (to, from, next) { }, beforeRouteUpdate ( to , from , next ) { // 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 `this` }, beforeRouteLeave ( to , from , next ) { // 导航离开该组件的对应路由时调用,可以访问组件实例 `this` }
beforeRouteEnter访问this
因为钩子在组件实例还没被创建的时候调用,所以不能获取组件实例 this ,可以通过传一个回调给 next 来访问组件实例 。
但是 回调的执行时机在mounted后面 ,所以在我看来这里对this的访问意义不太大,可以放在 created 或者 mounted 里面。
beforeRouteEnter (to, from, next) { console . log ( '在路由独享守卫后调用' ); next ( vm => { // 通过 `vm` 访问组件实例`this` 执行回调的时机在mounted后面, }) }
beforeRouteLeave:
导航离开该组件的对应路由时调用,我们用它来禁止用户离开,比如还未保存草稿,或者在用户离开前,将 setInterval 销毁,防止离开之后,定时器还在调用。
beforeRouteLeave (to, from , next) { if ( 文章保存 ) { next (); // 允许离开或者可以跳到别的路由 上面讲过了 } else { next ( false ); // 取消离开 } }
关于钩子的一些知识:
路由钩子函数的错误捕获
如果我们在全局守卫/路由独享守卫/组件路由守卫的钩子函数中有错误,可以这样捕获:
router.onError(callback => { // 2.4.0新增 并不常用,了解一下就可以了 console . log ( callback , 'callback' ); });
在路由文档中还有更多的实例方法:动态添加路由等,有兴趣可以了解一下。
跳转死循环,页面永远空白
我了解到的,很多人会碰到这个问题,来看一下这段伪代码:
router.beforeEach((to, from, next) => { if ( 登录 ){ next () } else { next ({ name : 'login' }); } });
看逻辑貌似是对的,但是当我们跳转到 login 之后,因为此时还是未登录状态,所以会一直跳转到 login 然后死循环,页面一直是空白的,所以:我们需要把判断条件稍微改一下。
if(登录 || to.name === 'login'){ next() } // 登录,或者将要前往login页面的时候,就允许进入路由
全局后置钩子的跳转: