Vue3 Router 4 完整教程(2026最新版):动态路由+权限控制+路由守卫
本文是 Vue3 系列教程从基础到进阶附完整代码示例收藏备用一、前言Vue Router 是 Vue.js 官方的路由管理器在 Vue3 中配合组合式 API 使用更加灵活高效。本文将从零开始带你掌握 Vue Router 4 的核心用法包括动态路由匹配、路由守卫实现权限控制、以及企业级项目中的最佳实践。学完本文你将掌握Vue Router 4 的基础配置与使用动态路由与嵌套路由的实现路由守卫实现登录鉴权基于角色的权限控制方案路由懒加载优化首屏性能二、环境准备与基础配置2.1 安装 Vue Router 4# 使用 npm npm install vue-router4 # 或使用 pnpm pnpm add vue-router42.2 创建路由配置文件创建src/router/index.jsimport { createRouter, createWebHistory } from vue-router import Home from ../views/Home.vue const routes [ { path: /, name: Home, component: Home }, { path: /about, name: About, component: () import(../views/About.vue) // 懒加载 } ] const router createRouter({ history: createWebHistory(), routes }) export default router2.3 在 main.js 中挂载路由import { createApp } from vue import App from ./App.vue import router from ./router const app createApp(App) app.use(router) app.mount(#app)三、路由基础用法3.1 声明式导航template nav !-- 使用 router-link 进行导航 -- router-link to/首页/router-link router-link :to{ name: About }关于/router-link !-- 激活状态样式 -- router-link to/ active-classactive-link首页/router-link /nav !-- 路由出口 -- router-view/router-view /template3.2 编程式导航script setup import { useRouter, useRoute } from vue-router const router useRouter() const route useRoute() // 跳转到指定路径 const goToAbout () { router.push(/about) } // 使用命名路由 const goToUser (userId) { router.push({ name: User, params: { id: userId } }) } // 替换当前路由不保留历史记录 const replaceToHome () { router.replace(/) } // 前进/后退 const goBack () { router.back() } // 获取当前路由信息 console.log(当前路径:, route.path) console.log(路由参数:, route.params) console.log(查询参数:, route.query) /script四、动态路由与嵌套路由4.1 动态路由匹配const routes [ // 动态段以冒号开头 { path: /user/:id, name: User, component: () import(../views/User.vue) }, // 多个动态段 { path: /user/:userId/post/:postId, name: UserPost, component: () import(../views/UserPost.vue) } ]在组件中获取参数script setup import { useRoute, onBeforeRouteUpdate } from vue-router import { ref, watch } from vue const route useRoute() const userId ref(route.params.id) // 监听路由参数变化 watch(() route.params.id, (newId) { userId.value newId fetchUserData(newId) }) // 或使用导航守卫 onBeforeRouteUpdate((to, from) { // 在当前路由改变但组件复用时调用 console.log(从, from.params.id, 到, to.params.id) }) const fetchUserData async (id) { // 获取用户数据 const res await fetch(/api/users/${id}) const data await res.json() // ... } /script4.2 嵌套路由const routes [ { path: /dashboard, component: () import(../views/Dashboard.vue), children: [ { path: , // 默认子路由 name: DashboardHome, component: () import(../views/dashboard/Home.vue) }, { path: profile, name: DashboardProfile, component: () import(../views/dashboard/Profile.vue) }, { path: settings, name: DashboardSettings, component: () import(../views/dashboard/Settings.vue) } ] } ]Dashboard.vue 模板template div classdashboard aside classsidebar router-link to/dashboard首页/router-link router-link to/dashboard/profile个人资料/router-link router-link to/dashboard/settings设置/router-link /aside main classcontent !-- 嵌套路由出口 -- router-view/router-view /main /div /template五、路由守卫实现权限控制5.1 全局前置守卫// router/index.js import { useUserStore } from ../stores/user router.beforeEach(async (to, from, next) { const userStore useUserStore() // 设置页面标题 document.title to.meta.title || 默认标题 // 判断是否需要登录 if (to.meta.requiresAuth) { if (!userStore.token) { // 未登录跳转到登录页 next({ path: /login, query: { redirect: to.fullPath } // 保存原目标路径 }) return } // 检查权限 if (to.meta.roles !to.meta.roles.includes(userStore.role)) { next(/403) // 无权限页面 return } } next() })5.2 路由配置中的权限控制const routes [ { path: /login, name: Login, component: () import(../views/Login.vue), meta: { public: true } // 公开页面 }, { path: /dashboard, component: () import(../views/Dashboard.vue), meta: { requiresAuth: true, title: 控制台 } }, { path: /admin, component: () import(../views/Admin.vue), meta: { requiresAuth: true, roles: [admin, superadmin], // 只允许管理员访问 title: 管理后台 } }, { path: /403, name: Forbidden, component: () import(../views/403.vue) } ]5.3 基于角色的动态路由生成// 定义所有可用路由 const asyncRoutes [ { path: /user-management, name: UserManagement, component: () import(../views/admin/UserManagement.vue), meta: { roles: [admin, superadmin] } }, { path: /system-settings, name: SystemSettings, component: () import(../views/admin/SystemSettings.vue), meta: { roles: [superadmin] } } ] // 根据用户角色筛选路由 function filterAsyncRoutes(routes, roles) { const res [] routes.forEach(route { const tmp { ...route } if (hasPermission(roles, tmp)) { if (tmp.children) { tmp.children filterAsyncRoutes(tmp.children, roles) } res.push(tmp) } }) return res } function hasPermission(roles, route) { if (route.meta route.meta.roles) { return roles.some(role route.meta.roles.includes(role)) } return true } // 在登录后动态添加路由 export function generateRoutes(userRoles) { const accessedRoutes filterAsyncRoutes(asyncRoutes, userRoles) accessedRoutes.forEach(route { router.addRoute(route) }) return accessedRoutes }六、路由懒加载与性能优化6.1 路由懒加载const routes [ { path: /heavy-page, component: () import(/* webpackChunkName: heavy */ ../views/HeavyPage.vue) } ]6.2 预加载关键路由// 预加载可能即将访问的页面 const lazyAbout () import(../views/About.vue) // 在用户鼠标悬停在链接上时预加载 const prefetchRoute () { lazyAbout() // 触发加载 }6.3 滚动行为控制const router createRouter({ history: createWebHistory(), routes, scrollBehavior(to, from, savedPosition) { // 如果有保存的位置浏览器前进/后退则恢复到该位置 if (savedPosition) { return savedPosition } // 如果有 hash滚动到对应元素 if (to.hash) { return { el: to.hash, behavior: smooth } } // 默认滚动到顶部 return { top: 0, behavior: smooth } } })七、常见问题与解决方案❌ 问题1刷新页面后 404原因使用createWebHistory时服务器需要配置回退到 index.html解决Nginx 配置location / { try_files $uri $uri/ /index.html; }或使用createWebHashHistoryURL 会带 #❌ 问题2路由守卫中无法访问 Pinia Store原因Store 在路由初始化时可能还未创建解决router.beforeEach((to, from, next) { const userStore useUserStore() // 在守卫内部获取 // ... })❌ 问题3动态路由刷新后失效原因动态添加的路由在页面刷新后会丢失解决在应用初始化时重新生成动态路由// main.js import { generateRoutes } from ./router const initApp async () { const userStore useUserStore() if (userStore.token) { await userStore.fetchUserInfo() generateRoutes(userStore.roles) } app.use(router) app.mount(#app) } initApp()❌ 问题4路由参数变化但组件不刷新解决使用onBeforeRouteUpdate守卫或监听$routeonBeforeRouteUpdate((to, from) { // 路由参数变化时执行 fetchData(to.params.id) })八、完整示例登录鉴权系统8.1 登录页 Login.vuetemplate div classlogin-page form submit.preventhandleLogin input v-modelform.username placeholder用户名 / input v-modelform.password typepassword placeholder密码 / button typesubmit登录/button /form /div /template script setup import { reactive } from vue import { useRouter, useRoute } from vue-router import { useUserStore } from ../stores/user const router useRouter() const route useRoute() const userStore useUserStore() const form reactive({ username: , password: }) const handleLogin async () { try { await userStore.login(form) // 登录成功后跳转到原目标页或首页 const redirect route.query.redirect || / router.push(redirect) } catch (error) { alert(登录失败 error.message) } } /script8.2 User Store// stores/user.js import { defineStore } from pinia import { ref, computed } from vue export const useUserStore defineStore(user, () { const token ref(localStorage.getItem(token) || ) const userInfo ref(null) const isLoggedIn computed(() !!token.value) const role computed(() userInfo.value?.role || ) const login async (credentials) { const res await fetch(/api/login, { method: POST, body: JSON.stringify(credentials) }) const data await res.json() token.value data.token userInfo.value data.user localStorage.setItem(token, data.token) } const logout () { token.value userInfo.value null localStorage.removeItem(token) } const fetchUserInfo async () { const res await fetch(/api/user/info, { headers: { Authorization: Bearer ${token.value} } }) userInfo.value await res.json() } return { token, userInfo, isLoggedIn, role, login, logout, fetchUserInfo } })九、总结本文详细介绍了 Vue Router 4 的核心功能基础配置安装、创建路由、挂载到应用导航方式声明式router-link和编程式useRouter动态路由参数匹配、监听变化、嵌套路由权限控制路由守卫、角色验证、动态路由生成性能优化懒加载、预加载、滚动行为最佳实践建议始终使用懒加载优化首屏性能路由守卫中做好权限校验和错误处理动态路由配合后端权限数据实现灵活控制注意浏览器刷新后动态路由的持久化问题觉得有用的话点个赞收藏关注我每周持续更新实战教程标签vue3 | vue-router | 前端 | 权限控制 | 路由守卫