Vue路由报错NavigationDuplicated:切换Workspace重载页面带新参数失败
问题场景
监听workspace状态变化时,通过$router.push跳转到同路由但不同参数的路径(如从/profile/c/123切换至/profile/p/321),控制台抛出错误:
Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "previous location".
当前实现代码:
@Watch('workspace') onWorkspaceChanged(o: Workspace, n: Workspace){ if(o.type === n.type && o.id === n.id) return; this.$router.push({name: this.$route.name as string, params: {id: `${n.id}`, type: `${ n.type == WorkspaceType.COMPANY ? COMPANY : PERSON }`}}); }
原因
Vue Router 3.x+版本中,默认会将同路由名称但参数不同的跳转判定为重复导航——内部通过fullPath判断是否重复,但实际我们需要更新参数并重新渲染页面。
解决方案
1. 捕获push的Promise异常
$router.push返回Promise,直接捕获重复导航的错误即可:
@Watch('workspace') onWorkspaceChanged(o: Workspace, n: Workspace){ if(o.type === n.type && o.id === n.id) return; this.$router.push({ name: this.$route.name as string, params: { id: `${n.id}`, type: `${ n.type == WorkspaceType.COMPANY ? COMPANY : PERSON }` } }).catch(err => { // 仅忽略重复导航错误,其他错误正常上报 if (err.name !== 'NavigationDuplicated') { console.error(err); } }); }
2. 用$router.replace替代push
如果不需要保留当前路由的历史记录,使用replace替换当前历史条目,不会触发重复导航错误:
@Watch('workspace') onWorkspaceChanged(o: Workspace, n: Workspace){ if(o.type === n.type && o.id === n.id) return; this.$router.replace({ name: this.$route.name as string, params: { id: `${n.id}`, type: `${ n.type == WorkspaceType.COMPANY ? COMPANY : PERSON }` } }); }
3. 全局处理重复导航错误
项目多处需要处理时,在路由初始化文件中全局修改push和replace方法:
// router/index.js import VueRouter from 'vue-router'; // 重写push方法 const originalPush = VueRouter.prototype.push; VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err); }; // 重写replace方法 const originalReplace = VueRouter.prototype.replace; VueRouter.prototype.replace = function replace(location) { return originalReplace.call(this, location).catch(err => err); };
4. 强制组件重新渲染
给路由视图绑定key为$route.fullPath,参数变化时组件会重新创建:
<!-- 根组件或父组件模板中 --> <router-view :key="$route.fullPath"></router-view>
也可以在目标组件内监听路由变化,手动处理业务逻辑:
@Watch('$route') onRouteChanged(to, from) { // 参数变化后重新请求数据或更新状态 }
内容的提问来源于stack exchange,提问作者Vladislav Uvarov
相关产品推荐
相关产品推荐

