嵌套路由 (Nested Routes)
1. 核心问题:为何需要嵌套路由?
在开发复杂应用时,常常会遇到一些页面共享相同的 UI 结构。例如,“用户中心”页面,无论你查看的是“个人资料”、“地址管理”还是“安全设置”,左侧的菜单栏总是固定不变的,只有右侧的内容区域在切换。
- 传统方式的弊端:如果为“资料”、“地址”、“安全”分别创建三个独立的完整页面,那么共通的左侧菜单栏部分就需要被复制三遍,造成代码冗余和维护困难。
- 嵌套路由的解决方案:将“用户中心”看作一个父级路由,其公共部分(如侧边栏)作为一个布局组件。具体变化的内容区域则作为子路由,动态渲染到布局组件中预留的占位符内。
2. 基础路由回顾
在理解嵌套路由前,我们先快速回顾一下基础的路由工作模式。
组件结构 (App.vue)
根组件 App.vue 通常包含全局导航链接 (<RouterLink>) 和一个路由出口 (<RouterView>)。
vue
<div id="app">
<nav>
<RouterLink to="/">首页</RouterLink>
<RouterLink to="/about">关于我们</RouterLink>
<RouterLink to="/user">用户中心</RouterLink>
</nav>
<RouterView />
</div><RouterLink>:生成导航链接,to属性指定目标路径。<RouterView>:一个占位符,路由匹配到的组件将会被渲染到这里。
路由配置 (router/index.js)
路由配置文件定义了路径 path 和组件 component 之间的映射关系。
javascript
// router/index.js
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// 路由懒加载
component: () => import('@/views/About.vue')
}
// ... 用户中心的路由配置将在这里展开
];当 URL 变化时,路由器会查找匹配的 path,并将对应的 component 渲染到 <RouterView> 中。
3. 嵌套路由的实现
现在,我们来解决“用户中心”的问题。
步骤 1: 创建布局组件 (Layout Component)
首先,为“用户中心”创建一个布局组件 UserLayout.vue。这个组件包含了共享的 UI(左侧菜单)和它自己的 <RouterView> 用于显示子页面。
vue
<div class="user-center">
<aside class="sidebar">
<RouterLink to="/user">用户资料</RouterLink>
<RouterLink to="/user/address">地址管理</RouterLink>
<RouterLink to="/user/security">安全设置</RouterLink>
</aside>
<main class="content">
<RouterView />
</main>
</div>步骤 2: 配置嵌套路由
在路由配置文件中,我们通过 children 属性来定义嵌套关系。
javascript
// router/index.js
const routes = [
// ... 其他路由(首页、关于)
{
// 1. 父路由路径
path: '/user',
// 2. 父路由渲染的组件,即布局组件
component: () => import('@/views/user/Layout.vue'),
// 3. 'children' 属性定义嵌套的子路由
// 当匹配到 /user 时,下面的组件会被渲染到 UserLayout.vue 的 <RouterView> 中
children: [
{
// path 为空字符串,表示这是 /user 路径下的默认子路由
// 当访问 /user 时,会匹配到此项
path: '',
component: () => import('@/views/user/Profile.vue')
},
{
// 子路由的 path 不以 '/' 开头。它会自动拼接在父路径之后
// 完整访问路径: /user/address
path: 'address',
component: () => import('@/views/user/Address.vue')
},
{
// 完整访问路径: /user/security
path: 'security',
component: () => import('@/views/user/Security.vue')
}
]
}
];关键点:
component: 父路由的component指向布局组件 (UserLayout.vue)。children: 一个数组,包含了所有子路由的配置对象。- 子路由
path:- 空字符串
'': 定义了父路径的默认子路由。当用户访问/user时,Profile.vue组件会被渲染。 - 相对路径
'address': 会被追加到父路径后面,形成完整的路径/user/address。
- 空字符串
4. 工作原理与优势
完整流程解析
当用户访问 /user/address 时,路由的解析过程如下:
- 匹配父路由: 路由器首先在顶层路由中匹配路径。
/user/address成功匹配到path: '/user'的父路由。 - 渲染父组件: 路由器将父路由对应的
UserLayout.vue组件渲染到根组件App.vue的<RouterView>中。 - 匹配子路由: 此时,路由器会继续使用路径的剩余部分 (
address) 在父路由的children数组中进行匹配。 - 渲染子组件: 路由器找到
path: 'address'的子路由,并将其对应的Address.vue组件渲染到父组件UserLayout.vue内部的<RouterView>中。
(这是一个概念图,说明了组件的嵌套关系)
核心优势
- 代码复用 (Reusability): 公共的UI布局(如侧边栏、顶部导航、页脚)只需在布局组件中编写一次,所有子页面均可复用。
- 结构清晰 (Clear Structure): 路由配置的嵌套结构直观地反映了组件和页面UI的层级关系,使得项目结构更易于理解和维护。
- 无限嵌套 (Infinite Nesting): 嵌套路由不限于两层。任何一个子路由本身也可以拥有自己的
children属性,实现三层、四层甚至更深层次的嵌套。例如,在“用户资料”页面内,还可以通过Tab选项卡进一步嵌套“基本资料”和“账户资料”等子视图。