Vue Router 是 Vue.js 官方推荐的路由解决方案,它通过管理 URL 实现单页应用(SPA)的页面跳转和组件切换。在实际项目中,我习惯把它比作"前台接待员"——当用户访问不同路径时,它能快速找到对应的"房间"(组件)并安排好"会面流程"(导航守卫)。
核心工作原理是通过监听浏览器地址变化,将路径与预先配置的组件映射关系进行匹配。与传统的页面跳转不同,Vue Router 只替换 DOM 中需要更新的部分,避免了整页刷新带来的性能损耗。这种机制使得应用能保持流畅的用户体验,特别适合需要频繁视图切换的后台管理系统、电商平台等场景。
首先通过 npm 安装最新版本(当前稳定版为 v4.x):
bash复制npm install vue-router@4
在项目中创建路由配置文件(通常为 src/router/index.js):
javascript复制import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
关键配置说明:
createWebHistory 使用 HTML5 History 模式(需要服务器支持)import())实现路由级代码分割process.env.BASE_URL 适配项目部署的子路径在主组件中使用 <router-view> 作为路由出口:
html复制<!-- App.vue -->
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view />
</div>
</template>
编程式导航的三种方式:
javascript复制// 方法1:字符串路径
router.push('/about')
// 方法2:带命名的路由
router.push({ name: 'about' })
// 方法3:带查询参数
router.push({ path: '/search', query: { q: 'vue' } })
通过冒号标记动态路径参数:
javascript复制{
path: '/user/:id',
component: UserView
}
在组件中通过 $route.params 获取参数:
javascript复制export default {
created() {
console.log(this.$route.params.id)
}
}
注意:当参数变化时(如从 /user/1 跳转到 /user/2),相同的组件实例会被复用,此时需要监听
$route变化或使用beforeRouteUpdate守卫
通过 children 属性实现布局嵌套:
javascript复制{
path: '/dashboard',
component: DashboardLayout,
children: [
{
path: '',
component: DashboardHome
},
{
path: 'settings',
component: DashboardSettings
}
]
}
对应的视图结构:
html复制<!-- DashboardLayout.vue -->
<template>
<div>
<Sidebar />
<div class="main-content">
<router-view />
</div>
</div>
</template>
通过 meta 字段存储路由额外信息:
javascript复制{
path: '/admin',
meta: { requiresAuth: true },
component: AdminPanel
}
结合导航守卫实现权限控制:
javascript复制router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.state.isAuthenticated) {
next('/login')
} else {
next()
}
})
推荐使用动态导入 + 魔法注释:
javascript复制{
path: '/heavy',
component: () => import(/* webpackChunkName: "heavy-page" */ './HeavyPage.vue')
}
Webpack 会将相同 chunkName 的组件打包到一起,优化加载性能。
创建路由时配置 scrollBehavior:
javascript复制const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else if (to.hash) {
return { el: to.hash }
} else {
return { top: 0 }
}
}
})
问题1:页面刷新后出现 404
nginx复制location / {
try_files $uri $uri/ /index.html;
}
问题2:路由跳转但组件不更新
javascript复制watch: {
'$route.params.id'(newVal) {
this.fetchData(newVal)
}
}
问题3:路由重复点击报错
javascript复制const originalPush = router.push
router.push = function push(location) {
return originalPush.call(this, location).catch(err => {
if (err.name !== 'NavigationDuplicated') throw err
})
}
根据用户权限生成动态路由:
javascript复制function generateRoutes(userRole) {
const baseRoutes = [...]
const adminRoutes = userRole === 'admin' ? [...] : []
return [...baseRoutes, ...adminRoutes]
}
const router = createRouter({
routes: generateRoutes(currentUser.role)
})
结合 <transition> 实现页面切换动画:
html复制<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
配套 CSS:
css复制.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
在导航守卫中预加载数据:
javascript复制router.beforeResolve(async to => {
if (to.meta.dataLoader) {
await to.meta.dataLoader()
}
})
路由配置示例:
javascript复制{
path: '/analytics',
component: AnalyticsView,
meta: {
dataLoader: () => store.dispatch('fetchAnalyticsData')
}
}
在大型项目中,我通常会封装一个路由配置校验器,确保每个路由对象都包含必要的 meta 字段。同时建议为路由名称添加命名空间前缀(如 app-home、admin-users),避免多人协作时的命名冲突。对于复杂权限系统,可以采用路由表后置处理方案——先定义完整路由结构,再根据权限动态过滤可用路由。