这是 qiankun + Vue Router 4 的一个已知冲突,根因在于两个 Vue Router 实例共享同一个 window.history,但各自的 base 不同。
Vue Router 4 的 history.state 机制Vue Router 4 每次导航时,会调用 history.pushState / history.replaceState
在 history.state 里存三个字段:
history.state = {
back: '/contracts', // 上一个路径
current: '/company-cert/business-license', // 当前路径
forward: null
}
关键点:这些路径是相对于 router 自己的 base 的。子应用 router 的 base 是 /archives,所以它存的是去掉 /archives 后的相对路径。
浏览器后退时发生了什么
-
用户在 /archives/company-cert/business-license 页面,点击浏览器后退
-
浏览器触发 popstate 事件
-
两个 router 同时监听到这个事件:
-
子应用 router(base = /archives):正确理解 state.back = '/contracts' 意思是 /archives/contracts
-
基座 router(base = /):也读到 state.back = '/contracts',但它认为这就是绝对路径 /contracts
-
基座 router 抢先处理,把 URL 导航到 /contracts
-
/contracts 在基座里没有对应路由 → 404
为什么没有子应用时不会出现?只有一个 Vue Router 实例时:
- 只有一个 router 读写 history.state
- 只有一个 base,路径的存和取是一致的
- 不存在"另一个 router 用不同的 base 来解读同一份 state"的问题
一句话总结:两个 router 共享一个 history.state,子应用写进去的是去掉 /archives 前缀的相对路径,基座读出来时当成了绝对路径,前缀就丢了。这是 Vue Router 4 + qiankun 的架构性冲突,所以才需要在基座的 beforeEach 里手动检测并补回前缀。