Vue Router之导航守卫

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

在讲解导航守卫前,我们需要理解几个参数:

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

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

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

  next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。

  next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。

  next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如   replace: truename: 'home' 之类的选项以及任何用在 router-linkto proprouter.push 中的选项。

  next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

一、全局守卫

1.全局前置守卫  router.beforeEach

// 配置路由
const router = new VueRouter({ ... })

//全局守卫的回调函数
router.beforeEach((to, from, next) => {
  // 这里执行具体操作
  // 如果没有next() 的话将不会进行跳转
})

这里的 to 是目标路由对象

    from 是当前路由对象

    next 是执行函数

例子:

// 配置路由
const router = new VueRouter({
  routes:[
    {path:'/',
    components:{ //嵌套命名,将component加s default为默认路由
      default:Home,
      theWork1:work1,
      theWork2:work2,
      theWork3:work3
    }},
    {path:'/works',component:Works,name:'WorksLink',redirect:'works/work1',
      children:[
        {path:'work1',component:work1},
        {path:'work2',component:work2},
        {path:'work3',component:work3}
      ]
    },
    {path:'/about',component:About},
    {path:"*",redirect:'/'} //默认跳转
  ],
  mode:'history'
})

router.beforeEach((to,from,next)=>{
  console.log("你想要进行跳转")
})

点击跳转,观察。

这里,我们点击发现,钩子已经执行了,由于没加next()所以不会进行跳转。

如果你学过ES6的话,你会发现导航守卫和我们的Proxy代理非常相似。

ok,加上next() 就可以正常跳转。

这个有什么用呢?

当当前访问的页面必须登陆的用户才能访问,我们就可以使用这个。

在进行 next 跳转之前,判断是否登陆,如果没登陆,就可以 跳转到登陆界面,让用户登陆。

2.全局后置守卫 router.afterEach 

按照套路,既然有before 那么很可能就有 after ,全局守卫也有afterEach。

由于,是在跳转后执行,所以不再接收next参数(我都跳转了,还要他干嘛!)

router.afterEach((to, from) => { //不接收next函数
  // 你想做的事
})

二、 路由独享的守卫

直接在配置路由是添加 beforeEnter

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // 三个参数和全局守卫一样
        // 仅在该组件上生效,不影响全局守卫
      }
    }
  ]
})

三、组件内的守卫

在组件内使用,如下:

<template>
    <div>
        <h1>About</h1>
        <h3>hi {{name}}</h3>
    </div>
</template>

<script>
export default {
    name: 'About',
    data(){
        return {
            name: 'YoungAm'
        }
    },
    beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
        next(vm=>{
            vm.name = "我是新名字"
        })
    },
    beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
        next()
    },
    beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
        next()
    }

}
</script>

注意,在 beforeRouteEnter 时,组件未被实例化,所以无法访问this。

在next中添加回调,此时 vm.name 相当于 this.name

 

 

posted @ 2019-05-15 09:36  本该如此  阅读(1401)  评论(0编辑  收藏  举报