vue2路由导航守卫(钩子函数)

官方:vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

所谓的Vue路由导航守卫,也就是我们常说的生命周期钩子函数,钩子函数的意思就是在特定的时刻,Vue会自动触发这个方法,我们可以通过这些个钩子函数,实现一些功能,比如,某些页面需要登录后才可以访问,某些页面需要用户达到什么等级才可以访问,又或者是跳转页面后修改一些信息等等,我们就可以通过路由导航守卫来拦截并做相应的处理

全局守卫:

挂载在router实例上

  • 全局前置钩子

注意:参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

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

        //to: Route: 即将要进入的目标 路由对象

        //from: Route: 当前导航正要离开的路由

        //next: Function:如果你想要进入下一个导航,就必须要调用next()方法,否则不会进入下一个导航
})

官方对于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() 注册过的回调。

看个小示例:

router.beforeEach((to,from,next)=>{
  if(to.matched.some((item)=>item.meta.login)){
    console.log(to)
    //router.app就是我们的根实例
    let info = router.app.$local.fetch('miaov')
    // console.log(info)

    if(info.login){
      next()
    }else{
      router.push({
        path:'/login'
      })
    }
  }else{
    next()
  }
})
  • 全局后置钩子:

注意:这些钩子不会接受next函数,也不会改变导航本身

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


})

局部钩子函数

局部钩子函数可以写在两个地方,一个是写在组件对应的路由配置中,一个是直接写在组件中

路由独享的守卫:

可以在路由配置上直接定义beforeEnter守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
        //参数和前置守卫的参数含义一样
      }
    }
  ]
})

组件内的守卫:

  1. beforeRouteEnter
  2. beforeRouteUpdata(2.2新增)
  3. beforeRouteLeave
beforeRouteEnter(to,from,next){
        
        //在渲染该组件的对应路由被confirm前调用
        //不能获取组件实例“this”
        //因为当守卫执行前,组件实例还没被创建

}

beforeRouteEnter 守卫不能访问this,因为守卫在导航确认前被调用,因此即将登场的新组建还没被创建

可以通过传一个回调给next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数

  export default {
    data(){
      return {
          flag: ''
      }
    },
    watch: {
      $route(){
        this.flag = flags[this.$route.path.slice(1)]
      }
    },
    beforeRouteEnter(to, from, next){//复用的,不会重新走钩子函数, 所以需要watch监控路由信息对象
      next((vm) => {
        vm.flag = flags[to.path.slice(1)]
      })
    },
    components: {
      headerNav: Header

      /*(resolve) => {
        setTimeout(() => {
          resolve(require('@/components/header'))
        }, 2000)
      }*/
    }
  }

 注意:beforeRouteEnter是支持给next传递回调的唯一守卫。对于beforeRouteUpdate和beforeRouteLeave来说
this已经可用了,所以不支持传递回调

beforeRouteUpdate(to,from,next){
        //在当前路由改变,但是该组件被复用时调用
        //可以访问组件实例this
        
}

这个函数应用场景比较特殊一点,当组件中有子导航时,我们就可以在这个父组件中使用这个方法来监控子路由的跳转了,然后再父组件中做出相应的处理,除了使用beforeRouteUpdate()函数外,我们还可以在父组件中使用watch来监控路由的变化,效果是差不多的,嗯,根据实际情况来判断该使用哪一种方式处理

  看个简单的小例子:

export default {
      data(){
       return{
         test:0
       }
      },
   //方法一 
      watch:{
        $route(){
          this.test++
        }
      },
      beforeRouteEnter(to,from,next){
        //this是个undefined,因为组件的实例还没有创建
        next((vm)=>{
          vm.test++
        });//next中可以接收一个回调函数
      },
   /*  方法二
      // beforeRouteUpdate(to,from,next){
      //   this.test++
      //   next();
      // },
   */
      beforeRouteLeave(to,from,next){
next();
      },
        name: "about"
    }
beforeRouteLeave(to,from,next){
        //导航离开该组件的对应路由时调用
        //可以访问组件实例this
}

离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过next(false)来取消

参考文章:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

你可能感兴趣的:(vue)