vue-router导航守卫

一、为什么需要导航守卫?

  有时候我们需要通过路由来进行一些操作,比如最常见的登录权限验证,当用户满足条件时,才让其进入导航,否则就取消跳转,并跳到登录界面让其登录

我们有很多方法植入路由的导航过程:全局的,单个路由独享的,或者组件级的

二、全局守卫

vue-router全局有三个守卫:
  1、router.beforeEach 全局前置守卫 ,进入路由前

  2、router.beforeResolve 全局解析守卫(2.5.0+),在beforeRouteEnter调用之后调用

  3、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"的选项

三、路由独享守卫

  const router = new Router({

    routes:[

      {

        path:'/foo',

        component:Foo,

        beforeEnter:(to,from,next) => {

          参数的用法都一样,调用的顺序在全局前置守卫的后面,所以不会被全局守卫覆盖

        }

      }

    ]

  })

四、路由组件内守卫

  1、beforeRouteEnter 进入路由前

  2、beforeRouteUpdate 路由复用同一组件时

  3、beforeRouteLeave 离开当前路由时

beforeRouteEnter (to,from.next) {

  //在路由独享守卫后调用,! 不 ! 能 获取组件实例this,组件实例还没有被创建

}

beforeRouteUpdate(to,from,next){

  //在当前路由改变,但是该组件被复用时调用,可以访问组件实例this

  //举例来说:对于一个带有动态参数的路径:/foo/:id,在/foo/1和/foo/2之间跳转的时候

  //由于会渲染同样的Foo组件,因此组件实例会被复用。这个钩子就会在这种情况下被调用

}

beforeRouteLeave(to,from,next){

  //导航离开该组件的对应路由时调用,可以访问组件实例

}

-------------------------------------------------------------

##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);//取消离开

    }

  }

五、关于钩子的一些知识

  1、路由钩子函数的错误捕获

    如果我们在全局守卫/路由独享守卫/组件路由守卫的钩子函数中有错误,可以这样捕获

    router.onError(callback => {

      console.log(callback,"callback")

    })

  2、跳转死循环,页面永远空白 

    router.beforeEach((to, from, next) => {

      if(登录){

        next();

      }else{

        next({name:"login"});

      }

    })

这样的逻辑看似是对的,但是当我们跳转到login之后,因为此时还是未登录状态,所以会一直跳转到login形成死循环

页面会一直空白,所以,我们要把判断条件稍微改变一下

  if(登录 || to.name === 'login'){ next() }

  //登录或者将要前往login页面的时候,就允许进路由

  3、全局后置钩子的跳转

  文档中提到因为router.afterEach()不接受next函数所以也不会改变导航本身:

    意思就是只能当成一个钩子来使用,但是也可以用于路由跳转

    //main.js入口文件

      import router from './router'  //引入路由

      router.afterEach((to,from) => {

        if(未登录 && to.name !== 'login'){

          router.push({name:"login"});  //跳转login

        }

      })

      

六、完整的路由导航解析流程(不包括其他生命周期)

  1、触发进入其他路由

  2、调用要离开路由的组件守卫:beforeRouteLeave

  3、调用全局前置守卫:beforeEach

  4、在重用的组件里调用:beforeRouteUpdate

  5、调用路由独享守卫:beforeEnter

  6、解析异步路由组件

  7、在将要进入的路由组件中调用:beforeRouteEnter

  8、调用全局解析守卫:beforeResolve

  9、导航被确认

  10、调用全局后置钩子的afterEach钩子

  11、触发DOM更新

  12、执行beforeRouteEnter守卫中传给next的函数

原文地址:https://www.cnblogs.com/jjbw/p/12132228.html