vue全站透传路由参数

有这么一个需求,如果请求连接中携带有q=0001,如:http://localhost:3000/index?q=0001,那么项目中后续所有跳转链接都需要加上q=0001。

vue 路由守卫

当然首先想到的是 vue 路由守卫中的全局前置守卫 beforeEach。

官方使用方法:

1
2
3
4
5
const router = new VueRouter({ ... })

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

如何添加全局参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
if (to.query['q']) {
// 如果存在参数,则直接进入下一页,否则会进入死循环
next()
return
}
// 全局携带参数q
const q = from.query['q']
if (q) {
to.query['q'] = q
next(to)
return
}
next()
})

以上代码已经完全能够实现所有路由携带参数 q,包括 <router-link>this.$router.push(xxx)

问题

如果项目刚好有用编程式路由导航 this.$router.push(xxx) 方式实现路由跳转,启动控制台,再点击跳转会发现有报错:

Uncaught (in promise) Error: Redirected when going from “xxx?q=0001” to “xxx” via a navigation guard.

<router-link> 并不会报以上错误,查看 push 方法源码会发现:

1
2
3
4
5
6
7
8
9
10
11
12
VueRouter.prototype.push = function push (location, onComplete, onAbort) {
var this$1 = this;

// $flow-disable-line
if (!onComplete && !onAbort && typeof Promise !== 'undefined') {
return new Promise(function (resolve, reject) {
this$1.history.push(location, resolve, reject);
})
} else {
this.history.push(location, onComplete, onAbort);
}
}

push 方法如果没传第二个 onComplete 参数和第三个 onAbort 参数,push 方法会返回一个 Promise 对象;

<router-link> 则使用的是 router.push(location, noop),其中 noop 为空函数 var noop = function () {};

报错原因就是调用了第三个参数 onAbort 方法,push 方法返回 Promise 时候调用了 reject;<router-link> 则会调用 onAbort,如果不传 onAbort = undefined 则不调用。

知道报错原因再找处理办法。

处理办法

可重写 push 方法,把 Promise 的错误 catch 捕获即可:

1
2
3
4
const originalPush = Router.prototype.push
Router.prototype.push = function push(...args) {
return originalPush.call(this, ...args)?.catch(err => err)
}

完整代码

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
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const originalPush = Router.prototype.push
Router.prototype.push = function push(...args) {
return originalPush.call(this, ...args)?.catch(err => err)
}

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

router.beforeEach((to, from, next) => {
if (to.query['q']) {
// 如果存在参数,则直接进入下一页,否则会进入死循环
next()
return
}
// 全局携带参数q
const q = from.query['q']
if (q) {
to.query['q'] = q
next(to)
return
}
next()
})
本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2021-07-02/vue-global-query/

如果您觉得文章不错,可以点击文章中的广告支持一下!