Vue2.0 Router 导航守卫

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

官方文档地址: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: truename: '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 和 路由独享守卫 四种守卫;

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('独享的守卫 beforeEach');
        next();
      }
    }
  ]
})

router.beforeEach((to, from, next) => {
  console.log("全局守卫 beforeEach");
  next();
})

router.beforeResolve((to, from, next) => {
  console.log('全局 beforeResolve');
  next()
})

router.afterEach((to, from) => {
  console.log('全局 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 组件切换)

在点击路由跳转按钮后,执行顺序

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 执行 路由home 的 keep-alive  的 deactivated 钩子
  12. 触发 DOM 更新 ,执行路由test 的 keep-alive  的 activated 的钩子
  13. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

 

以上个人学习理解,如有错误请指正 

 

posted @ 2018-12-21 15:34  每次醒来的徘徊  阅读(366)  评论(0编辑  收藏  举报