嵌套路由是 Vue Router 4 专为多层级布局应用设计的核心功能,通过树状结构实现父路由与子路由的关联映射。它可以让页面保持公共布局(如头部、侧边栏、底部)不变,仅动态切换核心内容区域,是后台管理系统、中台应用的标配路由方案。
/home/dashboard /home/products
+------------------+ +-----------------+
| Home | | Home |
| +--------------+ | | +-------------+ |
| | Dashboard | | +------------> | | Products | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+嵌套路由的核心逻辑:父路由组件保留固定布局,通过内置 <router-view> 渲染子路由对应的组件;子路由的路径无需书写完整父路径,路由系统会自动拼接。
例如访问 /home/dashboard,会渲染 Home 父组件,同时在其内部的 <router-view> 中渲染 Dashboard 子组件,实现布局复用与视图动态切换。
嵌套路由的基础是公共布局组件,我们基于 Vue 3 + Element Plus 搭建后台布局,作为父路由容器
修改 App.vue,作为整个应用的根容器:
<template>
<!-- 根路由视图,渲染父级布局组件 -->
<router-view />
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>创建 src/views/home/Home.vue,包含头部、侧边栏、内容区、底部,内容区通过 <router-view> 渲染子路由:
<template>
<el-container style="height: 100vh; box-sizing: border-box">
<!-- 顶部 Header -->
<el-header class="header">
<h1>我的应用</h1>
</el-header>
<!-- 主体布局 -->
<el-container>
<!-- 侧边栏导航 -->
<el-aside width="200px" class="aside">
<el-menu router :default-active="route.path">
<el-menu-item index="/home/dashboard">仪表盘</el-menu-item>
<el-menu-item index="/home/products">产品列表</el-menu-item>
</el-menu>
</el-aside>
<!-- 核心内容区:子路由渲染位置 -->
<el-main class="main">
<router-view />
</el-main>
</el-container>
<!-- 底部 Footer -->
<el-footer class="footer">
<p>版权所有 © 2025</p>
</el-footer>
</el-container>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';
// 获取当前路由,用于菜单激活
const route = useRoute();
</script>
<style scoped>
.header {
background-color: #303133;
color: #fff;
padding: 0 20px;
line-height: 60px;
}
.aside {
background-color: #ebeef5;
}
.main {
padding: 20px;
}
.footer {
text-align: center;
line-height: 60px;
background-color: #f0f2f5;
margin: 0;
}
</style>使用 children 配置项定义子路由,这是嵌套路由的核心语法;全局 404 路由必须放在最外层,不可嵌套在子路由中。
路由配置文件 src/router/index.ts:
import { createRouter, createWebHashHistory, type RouteRecordRaw } from 'vue-router';
// 导入布局组件
import Home from '../views/home/Home.vue';
// 导入子路由组件
import Dashboard from '../views/home/Dashboard.vue';
import Products from '../views/home/Products.vue';
// 导入全局 404 组件
import NotFound from '../views/error/404.vue';
const routes: Array<RouteRecordRaw> = [
{
path: '/home',
name: 'Home',
component: Home,
// 嵌套子路由配置
children: [
// 默认子路由:访问 /home 自动重定向到 /home/dashboard
{
path: '',
redirect: '/home/dashboard'
},
// 子路由:路径无需加 /,自动拼接父路径 /home/dashboard
{
path: 'dashboard',
name: 'Dashboard',
component: Dashboard
},
{
path: 'products',
name: 'Products',
component: Products
}
]
},
// 根路径重定向,优化用户体验
{
path: '/',
redirect: '/home'
},
// 全局 404 路由:必须放在配置最后(Vue Router 4 标准写法)
{
path: '/:catchAll(.*)',
name: 'NotFound',
component: NotFound
}
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router;创建子路由对应的页面组件,用于渲染在布局的内容区域。
src/views/home/Dashboard.vue
<template>
<div class="dashboard">
<h2>仪表盘</h2>
<p>欢迎来到后台管理仪表盘!</p>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.dashboard {
padding: 10px;
}
</style>src/views/home/Products.vue
<template>
<div class="products">
<h2>产品列表</h2>
<ul>
<li v-for="product in productList" :key="product.id">
{{ product.name }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
// 模拟产品数据
const productList = ref([
{ id: 1, name: 'Vue 3 实战课程' },
{ id: 2, name: 'Vue Router 4 教程' },
{ id: 3, name: 'Element Plus 组件库' }
]);
</script>
<style scoped>
.products {
padding: 10px;
}
li {
margin: 10px 0;
}
</style>src/views/error/404.vue
<template>
<div class="not-found">
<h1>404 - 页面未找到</h1>
<p>您访问的地址不存在,请检查后重试</p>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped>
.not-found {
text-align: center;
padding: 100px 0;
color: #f56c6c;
}
</style>路径写法
子路由 path 不需要以 / 开头,Vue Router 会自动拼接父路由路径;
例:父路径 /home + 子路径 dashboard = 完整路径 /home/dashboard。
默认子路由
通过 redirect 配置重定向,访问父路由时自动跳转至子路由,提升用户体验。
视图渲染
子路由组件只会渲染在父组件内部的 <router-view> 中,公共布局不会刷新。
路由优先级
路由按定义顺序匹配,精确路由优先级高于通配符路由,404 路由必须放在最后。
<!-- 直接写完整路径 -->
<router-link to="/home/dashboard">仪表盘</router-link>
<!-- 推荐:命名路由(无硬编码,更易维护) -->
<router-link :to="{ name: 'Dashboard' }">仪表盘</router-link>import { useRouter } from 'vue-router';
const router = useRouter();
// 跳转到产品列表
const goToProducts = () => {
router.push('/home/products');
// 推荐写法
// router.push({ name: 'Products' });
};