嵌套路由与路由懒加载
Vue Router 4 的嵌套路由和路由懒加载是构建复杂单页应用的两个重要特性。嵌套路由允许在父路由下渲染子路由组件,适合多级页面结构;路由懒加载则通过按需加载组件优化初始加载性能。本节将详细讲解这两者的实现方式、使用方法和应用场景,并通过示例展示如何在 Vue 3 项目中应用它们。
嵌套路由
嵌套路由通过在路由配置中定义 children 属性,实现父子路由的层级关系。
基本用法
路由配置
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
children: [
{ path: '', name: 'DashboardHome', component: () => import('@/views/DashboardHome.vue') },
{ path: 'profile', name: 'Profile', component: () => import('@/views/Profile.vue') },
{ path: 'settings', name: 'Settings', component: () => import('@/views/Settings.vue') }
]
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
父组件
<!-- src/views/Dashboard.vue -->
<template>
<div>
<h1>仪表盘</h1>
<nav>
<router-link to="/dashboard">首页</router-link>
<router-link to="/dashboard/profile">个人资料</router-link>
<router-link to="/dashboard/settings">设置</router-link>
</nav>
<router-view />
</div>
</template>
子组件
<!-- src/views/DashboardHome.vue -->
<template>
<p>欢迎来到仪表盘首页</p>
</template>
<!-- src/views/Profile.vue -->
<template>
<p>个人资料页面</p>
</template>
<!-- src/views/Settings.vue -->
<template>
<p>设置页面</p>
</template>
- 效果:
/dashboard显示“仪表盘”和“欢迎来到仪表盘首页”。/dashboard/profile显示“仪表盘”和“个人资料页面”。
- 解析:
children定义嵌套路由。- 父组件的
<router-view>渲染子组件。
动态嵌套路由
支持动态参数:
const routes = [
{
path: '/user/:id',
name: 'User',
component: () => import('@/views/User.vue'),
children: [
{ path: 'posts', name: 'UserPosts', component: () => import('@/views/UserPosts.vue') },
{ path: 'profile', name: 'UserProfile', component: () => import('@/views/UserProfile.vue') }
]
}
];
父组件
<!-- src/views/User.vue -->
<template>
<div>
<h1>用户 {{ route.params.id }}</h1>
<router-link :to="`/user/${route.params.id}/posts`">帖子</router-link>
<router-link :to="`/user/${route.params.id}/profile`">资料</router-link>
<router-view />
</div>
</template>
<script>
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
return { route };
}
};
</script>
- 效果:访问
/user/1/posts显示用户 1 的帖子页面。
路由懒加载
路由懒加载通过动态 import() 实现组件的按需加载,减少初始加载时间。
基本用法
配置懒加载
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{ path: '/', name: 'Home', component: () => import('@/views/Home.vue') },
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
- 效果:访问
/时加载Home.vue,访问/about时再加载About.vue。
与嵌套路由结合
const routes = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
children: [
{ path: '', component: () => import('@/views/DashboardHome.vue') },
{ path: 'profile', component: () => import('@/views/Profile.vue') }
]
}
];
- 效果:首次加载
Dashboard.vue,导航到子路由时按需加载对应组件。
异步组件优化
结合 defineAsyncComponent 添加加载状态:
import { defineAsyncComponent } from 'vue';
const routes = [
{
path: '/chart',
name: 'Chart',
component: defineAsyncComponent({
loader: () => import('@/views/Chart.vue'),
loadingComponent: { template: '<p>加载中...</p>' },
delay: 200
})
}
];
- 效果:访问
/chart时,加载前显示“加载中...”。
与 Suspense 集成
Vue 3 的 <Suspense> 可统一管理懒加载组件:
<!-- src/App.vue -->
<template>
<div>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<Suspense>
<template #default>
<router-view />
</template>
<template #fallback>
<p>加载中...</p>
</template>
</Suspense>
</div>
</template>
<script>
import router from './router';
export default {
setup() {
return { router };
}
};
</script>
- 注意:
<Suspense>是实验性特性,确保路由组件支持异步加载。
应用场景
嵌套路由
- 仪表盘布局:
- 父路由渲染导航栏,子路由切换内容。
- 用户管理:
/user/:id下嵌套帖子、资料等子页面。
- 多级菜单:
- 层级结构清晰展示。
路由懒加载
- 大型应用:
- 减少首屏加载时间。
- 按需模块:
- 如图表、编辑器等资源密集组件。
- 条件页面:
- 仅在特定路径加载。
综合示例
路由配置
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/shop',
name: 'Shop',
component: () => import('@/views/Shop.vue'),
children: [
{ path: '', name: 'ShopHome', component: () => import('@/views/ShopHome.vue') },
{
path: 'product/:id',
name: 'ShopProduct',
component: () => import('@/views/ShopProduct.vue')
}
]
},
{ path: '/:pathMatch(.*)*', component: () => import('@/views/NotFound.vue') }
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
组件实现
Shop.vue
<template>
<div>
<h1>商店</h1>
<router-link to="/shop">首页</router-link>
<router-link to="/shop/product/1">产品 1</router-link>
<router-link to="/shop/product/2">产品 2</router-link>
<Suspense>
<template #default>
<router-view />
</template>
<template #fallback>
<p>加载中...</p>
</template>
</Suspense>
</div>
</template>
ShopHome.vue
<template>
<p>欢迎来到商店首页</p>
</template>
ShopProduct.vue
<template>
<div>
<h2>产品 {{ route.params.id }}</h2>
<p>价格: ${{ price }}</p>
</div>
</template>
<script>
import { useRoute } from 'vue-router';
import { ref, onMounted } from 'vue';
export default {
setup() {
const route = useRoute();
const price = ref(0);
onMounted(() => {
const prices = { '1': 10, '2': 15 };
price.value = prices[route.params.id] || 0;
});
return { route, price };
}
};
</script>
- 效果:
/shop显示商店首页。/shop/product/1显示产品详情,懒加载生效。
注意事项
- 嵌套层级:
- 避免过深嵌套,增加维护难度。
- 懒加载性能:
- 确保必要组件预加载,优化用户体验。
- Suspense 兼容性:
- 检查组件是否支持异步渲染。
总结
嵌套路由通过 children 实现层级页面管理,路由懒加载通过动态导入提升性能。结合 Suspense,你可以打造高效、结构清晰的路由系统。本节的实践为你提供了实用技能,下一节将通过权限控制案例进一步巩固你的路由知识!
