详解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 相关文章推荐
权威JavaScript 中的内存泄露模式
Aug 13 Javascript
jquery制作搜狐快站页面效果示例分享
Feb 21 Javascript
jQuery实现的多屏图像图层切换效果实例
May 07 Javascript
使用jquery.qrcode.min.js实现中文转化二维码
Mar 11 Javascript
React组件的三种写法总结
Jan 12 Javascript
jQuery使用unlock.js插件实现滑动解锁
Apr 04 jQuery
原生JS实现层叠轮播图
May 17 Javascript
实现div内部滚动条滚动到底部和顶部的代码
Nov 15 Javascript
浅谈vue 单文件探索
Sep 05 Javascript
javascript实现对话框功能警告(alert 消息对话框)确认(confirm 消息对话框)
May 07 Javascript
layuiAdmin循环遍历展示商品图片列表的方法
Sep 16 Javascript
react使用CSS实现react动画功能示例
May 18 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中邮箱地址正则表达式实现与详解
2012/04/24 PHP
用Zend Studio+PHPnow+Zend Debugger搭建PHP服务器调试环境步骤
2014/01/19 PHP
php共享内存段示例分享
2014/01/20 PHP
Codeigniter整合Tank Auth权限类库详解
2014/06/12 PHP
PJ Blog修改-禁止复制的代码和方法
2006/10/25 Javascript
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
找出字符串中出现次数最多的字母和出现次数精简版
2012/11/07 Javascript
js 获取浏览器版本以此来调整CSS的样式
2014/06/03 Javascript
javascript结合Canvas 实现简易的圆形时钟
2015/03/11 Javascript
Java  Spring 事务回滚详解
2016/10/17 Javascript
JavaScript中数组的各种操作的总结(必看篇)
2017/02/13 Javascript
jquery请求servlet实现ajax异步请求的示例
2017/06/03 jQuery
JavaScript实现HTML5游戏断线自动重连的方法
2017/09/18 Javascript
通过vue提供的keep-alive减少对服务器的请求次数
2018/04/01 Javascript
jQuery实现DIV响应鼠标滑过由下向上展开效果示例【测试可用】
2018/04/26 jQuery
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
2019/02/27 jQuery
微信小程序如何修改本地缓存key中单个数据的详解
2019/04/26 Javascript
Python urllib模块urlopen()与urlretrieve()详解
2013/11/01 Python
跟老齐学Python之画圈还不简单吗?
2014/09/20 Python
Python+OpenCV让电脑帮你玩微信跳一跳
2018/01/04 Python
python调用API实现智能回复机器人
2018/04/10 Python
keras中模型训练class_weight,sample_weight区别说明
2020/05/23 Python
python如何调用百度识图api
2020/09/29 Python
利用canvas实现图片下载功能来实现浏览器兼容问题
2019/05/31 HTML / CSS
Shopee马来西亚:随拍即卖,最佳行动电商拍卖平台
2017/06/05 全球购物
医药大学生求职简历的自我评价
2013/10/17 职场文书
生产现场工艺工程师岗位职责
2013/11/28 职场文书
小学生防溺水广播稿
2014/01/12 职场文书
《我的第一本书》教学反思
2014/02/15 职场文书
法律进机关实施方案
2014/03/12 职场文书
四风对照检查材料思想汇报
2014/09/20 职场文书
2014年人力资源部工作总结
2014/11/19 职场文书
幼儿园大班教师评语
2019/06/21 职场文书
详解如何在Canvas中添加事件的方法
2021/04/17 Javascript
HTML+VUE分页实现炫酷物联网大屏功能
2021/05/27 Vue.js
python使用matplotlib绘制图片时x轴的刻度处理
2021/08/30 Python