详解vue-router的导航钩子(导航守卫)


Posted in Javascript onNovember 02, 2020

在做vue项目的时候,要求用户在页面访问前先登录,或在离开页面前发出提醒。vue官方提供的路由管理器 vue-router 提供的导航钩子,通过跳转或取消的方式守卫导航。以下总结了路由钩子函数的使用方法和一些使用场景。

一、全局守卫

router.beforeEach 路由改变前的钩子

const router = new VueRouter({ ... })

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

其中:

  • to:将要访问的路径
  • from:代表从哪个路径跳转来的
  • next:是一个函数,表示放行。有如下几种调用方式
    • next():如果一起正常,则调用该方法进入下一个钩子;
    • next(false):中断当前导航,即路由地址不发生变化;
    • next('/xxx') 或 next({path: '/xxx'}):强制跳转到指定路径;
    • next(error):如果传入的是一个Error实例,则导航会被中断且该错误会被传递给 router.onError() 注册过的回调。

使用:

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

该方法比较常用于:验证用户访问权限。

比如:一个系统需要先验证用户是否登录,如果登录了就可以访问,否则直接跳转到登录页面。具体实现如下:

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

router.beforeResolve 在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,该钩子函数就被调用。
该方法我在项目中暂时还未使用到,具体使用场景欢迎大家补充 :)

router.afterEach 路由改变后的钩子

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

该方法同全局前置守卫 router.beforeEach 不同的是少了 next() 函数,也不会改变导航本身。

使用场景:

路由切换,将页面的滚动位置返回到顶部。

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

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

二、路由独享的守卫

beforeEnter 对某个路由的单独守卫,在路由配置上直接定义

const routes = [
 { path: '/login', name: 'login', component: Login },
 { 
  path: '/home', 
  name: 'home', 
  component: Home,
  beforeEnter: (to, from, next) => {
   ... ...
  }
 }
]

const router = new VueRouter({
 routes
})

使用:

该方法的参数使用同全局前置守卫 router.beforeEach 是一样的;
例如:根据登录用户的不同角色,展示不同的模块;或者给指定路由组件单独添加动画。

import Vue from 'vue'
import VueRouter from 'vue-router'
import { getUserRole } from '@Utils/session.utils' // 登录用户的角色

const UserCenter = () => import('../pages/UserCenter.vue')

const routes = [
 ... ...
 { 
  path: '/usercenter', 
  name: 'usercenter', 
  component: UserCenter,
  beforeEnter: (to, from, next) => {
   if(getUserRole() === 'admin') next('/admincenter')
   else next()
  }
 }
]

三、组件内的守卫

beforeRouteEnter(to, from, next) 在进入当前组件对应的路由前调用

export default {
 data() { ... },
 beforeRouteEnter(to, from, next) {
  ... ...
 }
}

注意:

该函数内不能访问当前组件实例 this,因为函数在对应路由被 comfirm 前调用,此时将要渲染的组件实例还没被创建;

可以通过给 next 传递一个回调来访问组件实例,即把组件实例 vm 作为回调方法的参数;该回调的执行在 mounted 后面;

beforeRouteEnter (to, from, next) {
 next(vm => {
  // 通过 vm 来访问组件实例
 })
}

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

使用场景:

例如:从一个列表页进入到详情页,然后再返回到列表页,要求保留离开列表页之前访问的数据及滚动位置,从其他页面重新进入列表页,获取最新的数据。具体实现请点这里
beforeRouteUpdate(to, from, next) 在当前路由改变,但是该组件被复用时调用

beforeRouteUpdate (to, from, next) {
 ... ...
}

注:

该函数内可以访问当前组件实例 this

例如:在一个带有动态参数的路径 /detail/:id,在 /detail/aaa 和 /detail/bbb 之间跳转的时候,因为两个路由渲染的是同个 Detail 组件,因此原来的组件实例会被复用(比起销毁再创建,复用则会更加高效),在这种情况下这个钩子会被调用,而组件的生命周期钩子不会再被调用。

beforeRouteLeave(to, from, next) 在离开当前组件对应的路由前调用

beforeRouteLeave (to, from, next) {
 ... ...
}

注:

  • 该函数内可以访问当前组件实例 this;
  • 比如:用户在当前页面有还未保存的内容时突然离开,阻止页面跳转并给出提示,或者在用户离开时清除或存储一些信息等。

四、完整的导航解析流程

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

其实常用的也就那么几个,理解了其用法,路由导航的解析流程也就明了了。

五、附:使用 watch 监测路由变化

除了使用钩子函数外,我们也可以使用 watch 来监听 $route 对象,然后根据路由参数的变化来进行响应。

<template>
 <div id=``"app"``>
  <keep-alive>
   <router-view/>
  </keep-alive>
 </div>
</template>

<script>
 export default {
  name: 'App',
  watch: {
   '$route' (to, from) {
    // 对路由变化作出响应...
   }
  }
 }
</script>

到此这篇关于详解vue-router的导航钩子(导航守卫)的文章就介绍到这了,更多相关vue-router 导航钩子内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
BOM与DOM的区别分析
Oct 26 Javascript
Javascript中3种实现继承的方法和代码实例
Aug 12 Javascript
javascript中的this详解
Dec 08 Javascript
js随机生成网页背景颜色的方法
Feb 26 Javascript
JS实现网页背景颜色与select框中颜色同时变化的方法
Feb 27 Javascript
jquery实现网页的页面平滑滚动效果代码
Nov 02 Javascript
Bootstrap每天必学之缩略图与警示窗
Nov 29 Javascript
Bootstrap 折叠(Collapse)插件用法实例详解
Jun 01 Javascript
jQuery的Read()方法代替原生JS详解
Nov 08 Javascript
详解express使用vue-router的history踩坑
Jun 05 Javascript
微信小程序实现限制用户转发功能的实例代码
Feb 22 Javascript
vue使用openlayers实现移动点动画
Sep 24 Javascript
vue+elementUI中表格高亮或字体颜色改变操作
Nov 02 #Javascript
vue element-ui中table合计指定列求和实例
Nov 02 #Javascript
vue 动态添加class,三个以上的条件做判断方式
Nov 02 #Javascript
vue 公共列表选择组件,引用Vant-UI的样式方式
Nov 02 #Javascript
在vant 中使用cell组件 定义图标该图片和位置操作
Nov 02 #Javascript
Vant picker 多级联动操作
Nov 02 #Javascript
vue实现列表拖拽排序的功能
Nov 02 #Javascript
You might like
如何用PHP来实现一个动态Web服务器
2015/07/29 PHP
二级域名或跨域共享Cookies的实现方法
2008/08/07 Javascript
MC Dialog js弹出层 完美兼容多浏览器(5.6更新)
2010/05/06 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
2013/01/15 Javascript
jquery复选框checkbox实现删除前判断
2014/04/20 Javascript
jQuery实现切换页面过渡动画效果
2015/10/29 Javascript
Bootstrap每天必学之折叠
2016/04/12 Javascript
jquery对象访问是什么及使用方法介绍
2016/05/03 Javascript
详解JavaScript中双等号引起的隐性类型转换
2016/05/30 Javascript
javascript事件冒泡简单示例
2016/06/20 Javascript
BootStrap下拉菜单和滚动监听插件实现代码
2016/09/26 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
2016/12/19 Javascript
Js自动截取字符串长度,添加省略号(……)的实现方法
2017/03/06 Javascript
JS实现多级菜单中当前菜单不随页面跳转样式而发生变化
2017/05/30 Javascript
基于DOM节点删除之empty和remove的区别(详解)
2017/09/11 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
Vue 路由 过渡动效 数据获取方法
2018/07/31 Javascript
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
深入解读Python解析XML的几种方式
2016/02/16 Python
Python基于聚类算法实现密度聚类(DBSCAN)计算【测试可用】
2018/12/26 Python
pytorch多进程加速及代码优化方法
2019/08/19 Python
Python 寻找局部最高点的实现
2019/12/05 Python
浅谈tensorflow中张量的提取值和赋值
2020/01/19 Python
Python文件读写w+和r+区别解析
2020/03/26 Python
深入了解NumPy 高级索引
2020/07/24 Python
python学习笔记之多进程
2020/08/06 Python
全面介绍python中很常用的单元测试框架unitest
2020/12/14 Python
一站式跨境收款解决方案:Payoneer(派安盈)
2018/09/06 全球购物
澳大利亚游乐场设备品牌:Lifespan Kids
2019/05/24 全球购物
某同学的自我鉴定范文
2013/12/26 职场文书
拔河比赛口号
2014/06/10 职场文书
体育教育毕业生自荐信
2014/06/29 职场文书
五四青年节的活动方案
2014/08/20 职场文书
民主生活会对照检查材料范文
2014/10/01 职场文书
政风行风整改报告
2014/11/06 职场文书
大学生村官驻村工作心得体会
2016/01/23 职场文书