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
js
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)
js
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
js
router.addRoutes([
{
path: '/admin',
component: AdminLayout,
children: [
{ path: 'user', component: UserList },
],
},
]);
Vue Router 4
js
router.addRoute({
path: '/admin',
component: AdminLayout,
});
router.addRoute('admin', {
path: 'user',
component: UserList,
});
- 先添加父路由,再给父路由添加子路由。
- 返回
removeRoute方法可以卸载路由(做权限控制非常方便)。
🧪 路由守卫写法
Vue Router 4 的守卫新增了返回值写法:
js
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 }">,可以自定义渲染:vue<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 更顺手
ts
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()。 - 部署时检查服务器的历史模式配置。