Vue Router 3 升级 4:写法、坑点、兼容一次讲透
Vue 项目升级时,Router 往往被忽略。结果上线后刷新 404、动态路由失效、守卫不生效……今天我们把 Vue Router 3 → 4 的变化拆成三个部分:新写法、常见坑、兼容技巧,用最直白的方式让你迅速搞懂。
🧭 新旧对比:核心变化一眼看懂
| 点位 | Vue Router 3 | Vue Router 4 |
|---|---|---|
| 创建方式 | new Router({ ... }) | createRouter({ ... }) |
| 历史模式 | mode: 'history' | history: createWebHistory() |
| 动态添加路由 | router.addRoutes([...]) | router.addRoute('parent', route) |
| 路由守卫 | beforeEach((to, from, next) => {}) | 参数顺序相同,但必须显式返回值或调用 next() |
| 命名视图参数 | props: { default: true } | 写法一致,但 props 支持函数返回 |
| TypeScript 支持 | 需要额外类型声明 | 内置完整类型 |
🛠️ 创建路由的写法
Vue Router 3
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/views/Home.vue';Vue.use(Router);export default new Router({mode: 'history',routes: [{ path: '/', name: 'Home', component: Home },],
});
Vue Router 4(配合 Vue3)
import { createRouter, createWebHistory } from 'vue-router';
import Home from '@/views/Home.vue';const routes = [{ path: '/', name: 'Home', component: Home },
];const router = createRouter({history: createWebHistory(),routes,
});export default router;
- 不需要
Vue.use。 history改成函数。- 默认导入
createRouter、createWebHashHistory、createMemoryHistory。
🚦 动态路由怎么改?
Vue Router 3
router.addRoutes([{path: '/admin',component: AdminLayout,children: [{ path: 'user', component: UserList },],},
]);
Vue Router 4
router.addRoute({path: '/admin',component: AdminLayout,
});router.addRoute('admin', {path: 'user',component: UserList,
});
- 先添加父路由,再给父路由添加子路由。
- 返回
removeRoute方法可以卸载路由(做权限控制非常方便)。
🧪 路由守卫写法
Vue Router 4 的守卫新增了返回值写法:
router.beforeEach((to, from) => {const isLogin = Boolean(localStorage.getItem('token'));if (!isLogin && to.meta.requiresAuth) {return { name: 'Login', query: { redirect: to.fullPath } };}// 返回 undefined 或 true 表示放行
});
- 不再强制调用
next()。 - 也可以返回
false来取消导航。
🌍 刷新 404 怎么办?
- Vue Router 3:在生产环境加
try_files $uri $uri/ /index.html; - Vue Router 4:依旧如此,区别只是如果你用了
createWebHistory('/app/'),Nginx 也要配置子目录。
🔁 keep-alive 配合
- Vue Router 3 中
keep-alive通过include、exclude管控。 - Vue Router 4 配合
<RouterView v-slot="{ Component }">,可以自定义渲染:<RouterView v-slot="{ Component }"><KeepAlive include="UserList,UserDetail"><component :is="Component" /></KeepAlive> </RouterView> - 记得组件要有
name。
🧱 兼容 Vue2 项目:用 vue-router@4 + vue-demi?
- Vue Router 4 专为 Vue3 设计,不兼容 Vue2。
- 如果你还在 Vue2,可先升级到
vue-router@3.6,等待整体迁移完成后再上 4。 - Vue2 项目想体验组合式写法,可以用
@vue/composition-api插件,但 Router 要保持 3.x。
🧯 常见报错合集
| 报错 | 原因 | 解决 |
|---|---|---|
createRouter 未定义 | 仍在用 Vue Router 3 代码 | 确认安装 vue-router@4 并更新导入 |
| 刷新子路由 404 | 服务器没配置回退 | nginx try_files 或 Vite historyApiFallback |
| 动态路由不生效 | 忘记先添加父路由 | 先 addRoute(parent) 再加子路由 |
Navigation aborted | 守卫返回 false 或抛异常 | 检查守卫返回值 |
📦 搭配 TypeScript 更顺手
import { RouteRecordRaw } from 'vue-router';const routes: RouteRecordRaw[] = [{path: '/user/:id',name: 'UserDetail',component: () => import('@/views/UserDetail.vue'),props: (route) => ({ id: Number(route.params.id) }),},
];
RouteRecordRaw声明类型。props支持函数返回,类型安全。
✅ 总结行动清单
- 改写
createRouter+createWebHistory。 - 动态路由全部用
addRoute。 - 路由守卫返回值改成
return,不再使用next()。 - 部署时检查服务器的历史模式配置。
