第4章:Vue Router与路由权限

导航守卫调用链

全局前置守卫 beforeEach 路由独享守卫 beforeEnter 组件内守卫 beforeRouteEnter 全局解析守卫 beforeResolve 导航完成 afterEach+组件内 组件内后置钩子 组件内离开 beforeRouteLeave ⏱ 导航解析顺序: ①全局beforeEach → ②路由beforeEnter → ③组件beforeRouteEnter ④全局beforeResolve → ⑤导航完成afterEach → ⑥组件beforeRouteLeave
💡 加分提示:面试中说出“导航解析顺序”展现系统理解;强调全局解析守卫在异步组件加载后的唯一执行时机。

面试问答卡片

🔹 问题1:Vue Router 如何实现动态路由?

考察点:对 addRoutes / addRoute 的理解;路由合并时机;Vue3 下 addRoute 的使用差异。

回答框架:说明动态路由适用场景(权限菜单) → 调用 router.addRoute 追加路由 → 配合导航守卫进行权限判断。

// 登录后动态添加路由
router.addRoute({
  path: '/admin',
  name: 'Admin',
  component: () => import('./Admin.vue'),
  meta: { roles: ['admin'] }
});

示例回答(70字):“动态路由通过 router.addRoute 在登录后按角色追加。我会维护一个异步路由表,在 beforeEach 中判断用户是否已拉取权限,未拉取则调接口获取并 addRoute,再执行 next({...to,replace:true}) 确保导航生效。”

可能追问:①动态路由重复添加如何解决?②Vue3 中 addRoute 与 Vue2 的区别?③如何清空已添加的动态路由?

⚠ 避坑提醒:使用 addRoute 后必须用 next({...to,replace:true}) 重新触发导航,否则页面空白。Vue3 中已废弃 router.addRoutes,改为 router.addRoute 单条追加。

🔹 问题2:导航守卫中如何实现路由权限控制?

考察点:守卫链执行顺序;异步权限判断;白名单与路由 meta 设计;死循环避免。

回答框架:设定路由 meta.roles 标识所需权限 → 全局 beforeEach 检查登录状态 → 判断权限是否匹配 → 无权限跳转 403/登录页。

router.beforeEach((to, from, next) => {
  const  = store.state.;
  if (! && to.name !== 'Login') return next({name:'Login'});
  if (to.meta.roles && !to.meta.roles.includes(store.state.role)) 
    return next({name:'403'});
  next();
});

示例回答(85字):“我会在路由 meta 中定义 roles 白名单,在 beforeEach 中先校验 ,无 且不在白名单则跳登录。有 后检查 roles,不匹配则跳403页面。同时加入 vue-router 的 meta 字段扩展,支持通配符或函数式校验,避免硬编码。”

可能追问:①动态权限与静态权限如何混合管理?②嵌套路由中父路由与子路由权限继承如何处理?③导航守卫中异步请求权限数据怎么确保时序?

⚠ 避坑提醒:避免在守卫中连续调用 next() 导致死循环;异步请求后一定要 return 或 else 分支处理;403页面的路由本身不能添加权限校验。

🔹 问题3:路由懒加载的实现原理与最佳实践?

考察点:Webpack code splitting;Vue 异步组件语法;命名 chunk;预加载/预获取策略。

回答框架:使用动态 import() 实现按组分块 → webpackChunkName 指定 chunk 名称 → 配合魔法注释实现预加载。

// 懒加载 + 命名chunk
{
  path: '/dashboard',
  component: () => import(/* webpackChunkName: "dashboard" */ './views/Dashboard.vue')
}

示例回答(75字):“路由懒加载利用动态 import() 实现代码分割,每个页面独立打包。我会加 webpackChunkName 方便调试,对核心页面使用 /* webpackPrefetch: true */ 提前加载资源。同时注意不要频繁触发 chunk 重建,合理拆分页面与公共组件。”

可能追问:①预加载与预获取的区别?②Vite 下懒加载如何配置?③如何验证 chunk 是否被正确分割?

⚠ 避坑提醒:不要对需要即时响应的页面(如登录页)使用懒加载;避免动态 import 路径使用变量导致无法正确分割 chunk;生产环境注意 chunk 大小监控。

项目案例:跨端后台管理系统的路由权限重构

项目名称智能运营平台(PC+移动端H5)
业务背景企业级SaaS后台,支持多角色(超级管理员、运营、数据查看员)的菜单级权限控制,需同时适配PC与移动端浏览器。
规模指标路由总数78个;角色3类;日均活跃用户3000+;动态路由首次加载耗时从2.8s降至0.9s。
技术栈Vue 3 + Vue Router 4 + Pinia + Vite + TypeScript + Axios
核心难点①动态路由与静态路由合并时出现重复注册;②角色切换后旧路由未清理;③移动端首屏路由懒加载导致白屏。
面试高频追问①如何避免动态路由重复添加?②角色切换如何重置路由?③移动端如何优化首屏路由加载?
可迁移回答话术“采用路由白名单+动态addRoute方案,每次权限变更时通过 router.getRoutes() 比对,移除旧路由再添加新路由。移动端配合 /* webpackPrefetch */ 对前3个页面做预获取,配合骨架屏消除白屏体验。”
📌 项目经理提问应对:当被问及“如果后端返回的权限数据延迟,路由如何保证不空白?”回答:在 beforeEach 中加一个 async await 拉取权限,拉取失败时跳转502维护页,同时本地缓存权限数据做降级。
🚀 大厂面试加分点:理解 router.hasRoute / router.removeRoute 的语义;能说出“每次 addRoute 后应该重新记录 path 列表,防止内存溢出”;掌握 meta: { requiresAuth: true } 配合导航守卫做细粒度控制。