Vue Router 导航守卫

导航守卫

导航守卫

‘导航’表示路由正在发生改变。

vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。

路由跳转并不是任何时候都允许跳转,例如登录页面,只有用户名和密码输入正确才能跳转,而这时候就需要导航守卫来控制(阻拦和放行)

有很多方式植入路由导航中:全局的、单个路由独享的、组件级的。

参数(params)或查询(query)的改变并不会触发进入/离开的导航守卫,如果想在其改变时做些什么,可以通过watch $route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫

全局前置守卫

使用router.beforeEach注册一个全局前置守卫。

只要项目跳转,该方法一定会在跳转前触发。

对于全局守卫来说,单独创建一个js文件存放会更好。

each.js:

import router from "@/router/index";
router.beforeEach((to, from, next) => {
    //....
})

main.js:

import './router/each'

 每个守卫方法接收三个参数:to、from、next

举个栗子🌰:

现有路径'/'即将跳转到'/about'

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

from:Route  当前导航正要离开的路由(对象)

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

确保next函数在任何给定导航守卫中都被严格调用一次,可出现多于一次,但只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析(条件不满足,没有机会执行)或报错(逻辑路径冲突)。

带不同参数的next() 含义
next()

进行管道中的下一个钩子。

若去全部钩子都执行完了,则导航的状态就是confirmed(确认的)。

next(false)

中断当前导航。

若浏览器的URL改变了(用户手动或浏览器后退按钮),则URL地址会重置到from路由对应的地址。

next('/xxxx')或next({path:'/xxxx'})

跳转到一个不同的地址。当前导航被中断,然后进行一个新的导航。

可以向next传递任意位置对象,且允许设置如replace:true、name:'Home'之类的选项以及任何用在<router-link>的to属性或router.push()参数中的选项。

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

全局解析守卫

使用router.beforeResolve注册一个全局(解析)守卫。

与router.beforeEach类似,区别是在导航被确认之前(跳转前),同时在所有组件内守卫和异步路由组件被解析之后(解析后),解析守卫就被调用。

router.beforeResolve((to, from, next) => {
    //......
})

全局后置钩子

与守卫不同,这些后置钩子不会接受next函数也不会改变导航本身

守卫:导航前

钩子:导航后(已跳转,不需要next()了)

使用router.afterEach注册全局后置钩子。

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

路由独享的守卫

可以在路由配置上直接定义beforEnter守卫。

const routes = [
    {
        path: '/',
        component: () => import('@/views/Home'),
        beforeEnter: (to, from, next) => {
            //.......
        }
    }
]

组件内的守卫

在路由组件内直接定义以下路由导航守卫:

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
export default {
  name: "Home",
  beforeRouteEnter(to, from, next) {
    //......
  },
  beforeRouteUpdate(to, from, next) {
    //......
  },
  beforeRouteLeave(to, from, next) {
    //......
  }
}
  beforeRouteEnter beforeRouteUpdate beforeRouteLeave
触发

在渲染该组件的对应路由被confirm前调用

组件被复用时是不会调用beforeRouterEnter的

当前路由改变,但该组件被复用时调用

1.路由路径带有动态段,只有动态段变化

{
    path: '/:id',
    component: () => import('@/views/Home'),
}

2.路由路径从访问组件到访问子组件

子组件路由路径是绝对路径还是相对路径都可以

{
    path: '/home',
    component: () => import('@/views/Home'),
    children: [
        {
            path: 'about',
            component: () => import('@/views/About')
        }
    ]
}
导航离开该组件的对应路由时调用
是否可以获取this

不能获取组件实例‘this’

因为当该组件守卫执行前,组件实例还没被创建

可以访问实例'this'

可以访问实例'this'

针对this

通过传一个回调函数给next(),来访问组件实例

在导航被confirm的时候执行回调,且把组件实例作为回调方法的参数

beforeRouteEnter(to, from, next) {
  next(vm => {
    //.....
  });
}
   
是否支持给next传递回调 是(唯一支持的守卫) 否 (能直接访问this,没必要) 否(能直接访问this,没必要)
应用    

通常用来禁止用户在还未保存修改前突然离开,阻止导航,且询问用户是否未保存就离开

next() 放行   next(false) 取消导航,留在当前页面

beforeRouteLeave(to, from, next) {
  const answer = window.confirm('还未保存,是否离开?');
  if (answer) {
    next();
  } else {
    next(false);
  }
}

完整的导航解析流程

1.导航被触发(接收到from路由,且上一轮的导航已经结束,但仍停留在上一个组件里)(触导)

2.在失活的组件里调用beforeRouteLeave守卫(离失活组)

3.调用全局beforeEach守卫(全进)

4.如果存在复用的组件,在复用组件里调用beforeRouteUpdate守卫(复组更)

5.在路由配置里调用beforeEnter(路进)

6.解析异步路由组件(解析异步路)

7.在被激活的组件里调用beforeRouteEnter(进激活组)

8.调用全局beforeResolve守卫(全析)

9.导航被确认(confirm)

10.调用全局afterEach钩子(全完)

11.触发DOM更新     但这时候还没有执行生命周期钩子,还没有创建vue实例并挂载,所以只是页面数据当前并没有发生改变

12.调用beforeRouteEnter守卫中传给next的回调函数,创建好的实例会作为参数传入(组件实例建好传回调)

守卫/钩子总结🥗:

全局3个(2守卫 1钩子):beforeEach、beforeResolve、afterEach

路由守卫1个:beforeEnter

组件守卫3个:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

posted @ 2021-10-17 22:52  慕斯星球  阅读(239)  评论(0)    收藏  举报