vue-router 增加全局 query 参数导致后 replace 跳转失败

发现这个问题是因为最近给我司的商城系统扩展了一个功能,就是所有路由都需要带上 shopid(店铺ID)。

这个功能实现并不复杂,在前置导航守卫里就能处理。

1
2
3
4
5
6
7
8
router.beforeEach((to, from, next) => {
if (!to.query.shopid) {
to.query.shopid = store.state.global.shopid
next(to)
} else {
next()
}
})

思路就是在前置导航守卫里判断目标路由的 query 里是否有 shopid ,如果没有则手动加上,并中断当前导航,跳转到新的导航。

发现问题

问题在这里就出现了,在 next(object) 中如果传递对象,这时跳转另一个地址默认是用 push 方式,而非 replace

虽然文档里有写,可以通过设置 replace: true 让跳转操作实现 replace 跳转,但因为我这里是一个全局的操作,无法预估出项目中哪些是用 push 跳转,哪些是用 replace 跳转。并且在前置导航守卫里,也无法获取到任何关于进入目标路由是通过 push 还是 replace 的信息。

解决思路

于是只能转变思路,既然导航守卫无法解决,那就只能退而求其次,用笨一点的方式解决。

我的方案是:在所有用 replace 跳转的地方,手动给 query 里增加 replace: true 的参数设置,然后在前置导航守卫里处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
router.beforeEach((to, from, next) => {
if (!to.query.shopid) {
const newTo = {
name: to.name,
path: to.path,
query: Object.assign(to.query, {
shopid: store.state.global.shopid
}),
params: to.params
}
if (to.query.replace) {
newTo.replace = true
delete to.query.replace
}
next(newTo)
} else {
next()
}
})

使用的时候就是这样:

1
<RouterLink :to="{path:'/example/page',query:{replace:true}}" replace>测试页面</RouterLink>
1
2
3
4
5
6
this.$router.replace({
path: '/example/page',
query: {
replace: true
}
})

这就是我目前的解决办法,虽然有点麻烦,不过好在项目中使用到 replace 跳转的地方不多,处理起来也不会太麻烦,当然也可以单独封装一个全局 replace 跳转的方法,在方法里统一处理,这样项目中需要用到 replace 跳转的地方就可以调用自己封装的方法,也避免了忘记给 query 增加 replace: true 的参数设置。

参考