Vue嵌套路由

在单页应用里,"页面"不再是整屏刷新,而是由路由驱动的组件树。当业务复杂到「用户中心 → 个人资料 / 收货地址 / 账号安全 / 好友列表」这种层级时,嵌套路由(Nested Routes)是唯一能把深度与可维护性同时保留下来的方案。

一、嵌套路由到底在解决什么问题

想象一个用户中心:

bash 复制代码
/user                 用户中心外壳(Layout)
├── /user/profile     个人资料
├── /user/address     收货地址
├── /user/security    账号安全
└── /user/friends     好友列表

如果写成平级路由,每切换一个子页面就要重新加载整个外壳(导航、侧边栏、用户信息),浪费、卡顿、状态丢失。

嵌套路由让外壳只挂载一次,子页面作为 <router-view> 的局部插槽渲染,完美复用外壳,并天然支持面包屑、标签页、权限控制。

二、一条代码看全貌

js 复制代码
// router/index.js
const routes = [
  {
    path: '/user',
    component: () => import('@/views/user/Layout.vue'), // 外壳
    children: [
      { path: '',           component: () => import('@/views/user/Profile.vue') },
      { path: 'address',    component: () => import('@/views/user/Address.vue') },
      { path: 'security',   component: () => import('@/views/user/Security.vue') },
      { path: 'friends',    component: () => import('@/views/user/Friends.vue') }
    ]
  }
]

要点:

  • 层级关系 = 文件系统:父路由的 component 是文件夹,children 是里面的文件。
  • 默认子路由 = 空字符串 '',访问 /user 时自动渲染 Profile
  • 路径写法 = 相对路径:address 会自动拼接成 /user/address,无需手写全量。

三、Layout 组件

vue 复制代码
<!-- views/user/Layout.vue -->
<template>
  <div class="user-center">
    <aside>
      <router-link to="/user">个人资料</router-link>
      <router-link to="/user/address">收货地址</router-link>
      <router-link to="/user/security">账号安全</router-link>
      <router-link to="/user/friends">好友列表</router-link>
    </aside>
    <main>
      <router-view />   <!-- 子路由插在这里 -->
    </main>
  </div>
</template>

子页面渲染时,Layout 组件不会重新创建,导航高亮、用户信息、WebSocket 连接全部保持。

四、动态路由 + 嵌套:URL 即状态

把用户 ID 塞进路径:

js 复制代码
{
  path: '/user/:id',
  component: () => import('@/views/user/Layout.vue'),
  props: true,              // 把 id 作为 prop 注入 Layout
  children: [
    { path: '',        component: () => import('@/views/user/Profile.vue'), props: true },
    { path: 'address', component: () => import('@/views/user/Address.vue'),  props: true }
  ]
}

访问 /user/42/address 时:

  • Layout 通过 props.id 拿到 42,去拉用户信息;
  • Address 通过 props.id 再去拉地址列表;
  • 切换子路由只改后半段,外壳复用,接口只增不重复。

五、项目实践

1.权限与面包屑

js 复制代码
{
  path: '/user',
  component: Layout,
  meta: { title: '用户中心', needAuth: true },
  children: [
    { path: '', meta: { title: '个人资料' } },
    { path: 'address', meta: { title: '收货地址' } }
  ]
}

全局后置钩子:

js 复制代码
router.afterEach(to => {
  document.title = to.matched
    .map(r => r.meta.title)
    .filter(Boolean)
    .join(' - ')
})

matched 数组从根到当前节点依次展开,天然就是面包屑数据源。

权限同理:在导航守卫里检查 to.matched.some(r => r.meta.needAuth),一次递归即可拿到所有层级要求。

2.代码分割

  • 父路由同步加载:外壳体积小,保证首屏骨架秒出;
  • 子路由全部懒加载:利用魔法注释给 chunk 命名,方便 CDN 缓存。
js 复制代码
component: () =>
  import(/* webpackChunkName: "user-security" */ '@/views/user/Security.vue')

六、常见问题

  • 空路径与斜杠:path: ''path: '/' 都匹配 /user,但后者会额外触发重定向,导致外壳重复渲染。
  • 深度监听失效:在 Layoutwatch $route 时,记得加 immediate: true,否则首次进入不触发。
  • 滚动位置丢失:给 <router-view>key="$route.fullPath" 可强制重新挂载,但会破坏缓存;更优解是在 activated 钩子里手动恢复 scrollTop。
相关推荐
程序员agions5 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发5 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_6 小时前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞056 小时前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、6 小时前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao6 小时前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly6 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
愚者游世6 小时前
Delegating Constructor(委托构造函数)各版本异同
开发语言·c++·程序人生·面试·改行学it
一 乐6 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
科技D人生6 小时前
Vue.js 学习总结(20)—— Vue-Office 实战:word、pdf、excel、ppt 多种文档的在线预览
vue.js·word·vue-pdf·stylesheet·docx-preview·vue-office