核心是直接导入并使用已创建的路由实例,如import router from '@/router'; router.push('/login'),而非调用userouter等组合式api;必须确保路由文件导出的是createrouter()返回的实例,而非仅路由配置数组。

在非组件文件(比如 Axios 拦截器、工具函数、请求封装层)中实现路由跳转,核心是绕过 Vue/React 的响应式上下文限制,直接拿到可调用的路由实例。不能用 useRouter 或 useHistory,因为它们只能在组件或 Hook 内部执行。关键不是“怎么跳”,而是“怎么提前拿到那个能跳的对象”。
Vue 3:从 router/index.ts 直接导出路由实例
确保你的路由配置文件(通常是 src/router/index.ts 或 .js)导出的是一个已创建好的 router 实例,而不是仅导出配置数组:
- ✅ 正确写法(导出实例):
import { createRouter, createWebHistory } from 'vue-router'<br>
const router = createRouter({<br>
history: createWebHistory(),<br>
routes: [...]<br>
})<br>
export default router // ← 这里导出的是 router 实例
- ❌ 错误写法(只导出配置):
export const routes = [...] // 无法直接 .push()
之后在 axios.interceptors.response.use 中直接导入并使用:
import router from '@/router'<br>
// ...<br>
if (res.data.code === 401) {<br>
localStorage.removeItem('token')<br>
router.push('/login')<br>
}
React(v6+):用 history 库单独管理导航实例
React Router v6 移除了全局 history API,但可通过 history 包自行创建并统一注入:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 安装:
npm install history - 新建
src/utils/history.ts:
import { createBrowserHistory } from 'history'<br>
const history = createBrowserHistory()<br>
export default history
- 在根组件(如
main.tsx或App.tsx)中用HistoryRouter替代Router:
import { HistoryRouter } from 'react-router-dom'<br>
import history from './utils/history'<br>
// ...<br><historyrouter history="{history}"><br>
<app></app><br></historyrouter>
之后任意非组件文件(如 src/utils/request.ts)中即可导入跳转:
import history from '@/utils/history'<br>
if (error.response?.status === 401) {<br>
localStorage.removeItem('token')<br>
history.push('/login')<br>
}
通用避坑提醒
避免以下常见错误操作:
- 在拦截器里反复
createBrowserHistory()—— 每次新建 history 是独立实例,不会触发页面更新 - 用
window.location.href = '/login'强刷页面 —— 破坏 SPA 体验,丢失状态,且不走路由守卫逻辑 - 试图在
setup()外调用useRouter()—— Vue 会报 “must be called at the top of a setup function” - 导出路由配置数组而非实例后,在工具文件里尝试
router.push—— 会提示 “push is not a function”
补充:为什么必须“提前导出”?
框架的路由系统本质是一个单例状态机。只有把实例提前创建好、导出、并在整个应用中复用同一个对象,才能保证跳转行为被 Router 组件监听到。临时 new 一个、或只导出配置,等于造了个“没连上总线”的遥控器——按了键,设备根本收不到信号。










