vue-router中的路由钩子函数基本用法汇总

3,108 阅读3分钟

最近学习了下vue-router,发现有很多钩子函数,所以打算整理一下

路由钩子函数分为三种

第一种:全局钩子函数

router.beforeEach((to, from, next) => {
  // ...在跳转前做一些事
  next() //正常跳转,不写的话,不会跳转
})
router.afterEach(() => { 
  if (width <= 500){
        menuVisible.value = false
})//在跳转后做一些事情

to:router即将进入的路由对象

from:当前导航即将离开的路由

next:Function,进行管道中的一个钩子,如果执行完了,则导航的状态就是 confirmed (确认的);否则为false,终止导航。

  • next():如果一直正常,则调用该方法进入下一个钩子;
  • next(false):中断当前导航,即路由地址不发生变化;
  • next('/xxx') 或 next({path: '/xxx'}):强制跳转到指定路径;
  • next(error):如果传入的是一个Error实例,则导航会被中断且该错误会被传递给 router.onError() 注册过的回调。

第二种:针对单个路由钩子函数

写在路由配置中,只有访问到这个路径,才能触发钩子函数

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
        next() //正常跳转,不写的话,不会跳转
      }
    }
  ]
})

这些钩子与全局 before 钩子的方法参数是一样的

第三种:组件内的钩子

写在组件中,访问路径,即将渲染组件的时候触发的

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 渲染 前调用
    // 不能获取组件实例 `this`
    // 因为当钩子执行前,组件实例还没被创建
     next((vm) =>{
                vm就是实例// next来访问组件实例,就可以访问实例‘this’,在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
        })
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

注意: beforeRouteEnter 是支持给 next 传递回调的唯一守卫。

一些使用场景:

beforeRouteLeave():

1.beforeRouteLeave():通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。 清除定时器,清除缓存

beforeRouteLeave (to, from, next) {
 window.clearInterval(this.timer) //清除定时器
 next()
}

2.禁止用户在还未保存修改前突然离开。

beforeRouteLeave (to, from, next) {
 const answer = window.confirm('你的修改内容未保存,你确定要离开吗?')
 if(answer){
 next()
 }else{
 next(flase)
 } 
}

3.当用户需要关闭页面时, 可以将公用的信息保存到session或Vuex中

beforeRouteLeave (to, from, next) {
  localStorage.setItem(name, content); //保存到localStorage中
  next()
}

beforeEach()

使用该函数,一定要调用 next(),否则钩子函数不能 resolve;

1.验证用户访问权限。一个系统需要先验证用户是否登录,如果登录了就可以访问,否则直接跳转到登录页面。

import Vue from 'vue'
import VueRouter from 'vue-router'
import { getToken } from '@Utils/session.utils' // 登录用户的token
import Login from '../pages/Login.vue' //引入登录页
const Home = () => import('../pages/Home.vue') //引入首页
 
Vue.use(VueRouter) // 全局注入router
 
// 配置路由参数
const routes = [
 { path: '/login', name: 'login', component: Login },
 { path: '/home', name: 'home', component: Home }
]
 
const router = new VueRouter({
 routes
})
 
// 全局挂载路由导航守卫:验证用户是否登录
router.beforeEach((to, from, next) => {
 if (to.name !== 'login' && !getToken()) next('/login') // 如果用户不是访问登录页且没有登录,则强制跳转到登录页
 else next()
})
 
export default router

afterEach()

1.路由切换,将页面的滚动位置返回到顶部。页面比较长,当滚动到某个位置后切换路由,这时跳转的页面滚动条位置默认是前一个页面离开时停留的位置,可以通过该钩子函数将滚动条位置重置。

// 切换路由,页面返回到顶部
router.afterEach((to, from) => {
 window.scrollTo(0, 0)
})

2.当页面跳转后,判断当前页面的宽度大小后,选择是否隐藏侧边栏

 const width = document.documentElement.clientWidth;
 const menuVisible = ref(width > 500);
 provide('menuVisible',menuVisible)//set
 router.afterEach(()=> {
      if (width <= 500){
        menuVisible.value = false
      }

beforeRouteEnter()

从一个列表页进入到详情页,然后再返回到列表页,要求保留离开列表页之前访问的数据及滚动位置,从其他页面重新进入列表页,获取最新的数据,

(在组件切换过程中将状态保留在内存中,等再次访问的时候,还保持着离开之前的所有状态,而不是重新初始化。)使用的是vue缓存之<keep-alive>

具体的使用参考文章 www.jb51.net/article/198…

完整的导航解析流程

  • 导航被触发;
  • 在失活的组件里调用 beforeRouteLeave 守卫;
  • 调用全局的 beforeEach 守卫;
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+);
  • 在路由配置里调用 beforeEnter;
  • 解析异步路由组件;
  • 在被激活的组件里调用 beforeRouteEnter;
  • 调用全局的 beforeResolve 守卫 (2.5+);
  • 导航被确认;
  • 调用全局的 afterEach 钩子;
  • 触发 DOM 更新;
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。