Vue 动态添加路由

本文将介绍在 Vue 中使用动态添加路由这一技术点时,遇到的问题及其解决方案。

一、动态添加路由

1. 什么是动态添加路由?

有些时候,希望路由映射并非一开始便写死在 js 文件之中,而是在运行过程中动态添加。

Vue Router 提供了 addRoutes() 方法,可以用于完成这一需求。

2. 使用场景

  • 待用户登录完成后,才为用户添加除登录和注册以外的路由
  • 在运行时,根据用户类型,动态添加权限路由

二、动态添加的路由刷新后丢失

1. 问题

在开发中,动态添加路由,路由能够被顺利添加并访问,但刷新页面后路由便会丢失,页面显示白屏。

2. 产生原因

动态添加的路由将会在页面刷新后丢失。

3. 解决思路

检测页面是否刷新,一旦页面刷新,便重新添加路由。

4. 注意点

  • 由于 Vuex 和动态添加的路由一样,会在刷新后丢失,因此可以检测 Vuex 中数据的状态,从而间接检测页面是否刷新
  • 不应在动态添加路由后便放行,而是应该在路由添加完成之后再放行

三、解决方法

1. 做法

  • 通过全局前置守卫路由,在每次路由跳转之前拦截
  • 由于动态添加的路由将会在刷新页面后消失,因此需要判断页面是否刷新,如果页面发生了刷新,应该重新添加路由
  • 由于 Vuex 中的数据同样会在刷新后丢失,因此可以借助 Vuex 进行页面刷新的判断
  • 由于路由的动态添加需要时间,因此不应该直接添加路由并放行,而是应该通过 next({ ...to, replace: true }) 在路由被成功添加之前不断跳转进入新的导航,等待路由被添加

2. 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Vue.use(Router)

const routes = [
···路由映射表···
]

const router = new Router({
routes
})

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {

// 获取需要被动态挂载的路由映射表
let dynamicRoutes

// 如果从未动态添加路由,或页面发生了刷新,则Vuex中的数据将为默认值
if (Vuex中的数据为默认值) {

// 修改Vuex中的数据
···

// 动态添加路由
router.addRoutes(dynamicRoutes)

// 确保路由添加后才进行放行
next({ ...to, replace: true })
}

// 无需添加,直接放行
next()
})

export default router

3. next({ …to, replace: true })

(1) next()

  • next() 代表放行
  • next('/路径') 代表跳转至指定路径
  • next({path: '/路径', ···}) 代表跳转至指定路径,可以在对象中设置诸如 replace: truename: 'home' 等选项

next(...) 将会中断当前的导航,并进入新的导航,因此新的导航也会被导航守卫拦截。

(2) to

to 是全局前置守卫的参数,代表即将进入的目标路由对象。

(3) 扩展运算符

...:扩展运算符,其作用是:取出目标对象中的所有可遍历属性,拷贝至当前对象之中

具体请看:

JavaScript ES6

(4) next({ …to })

next({ ...to }) 的作用是:将即将进入的目标路由对象拷贝一份,跳转至其中。

在上述代码中,

  • 未动态添加路由,因此进行动态添加,并进入新的导航
  • 由于进入了新的导航,因此会再次被全局前置守卫拦截
  • 如果在新的导航中,路由还未成功添加,便会再次执行 next({ ...to }) 进入新的导航
  • 如此循环往复,直至路由添加成功,执行 next() 放行

(5) next({ …to, replace: true })

next({ ...to, replace: true }) 的作用是:在 next({ ...to }) 的基础上,使用 “替换” 的方式修改路径,使得用户无法通过浏览器上的后退按钮进行无效的后退。

参考