问题及背景
背景
Vite + Vue3 项目,想要实现如下图的效果:
父页面有几个按钮,跳转到子页面;子页面可以返回到父页面。
问题
交互很简单,但是父页面和子页面都是全屏展示,一样的大小,它们之间没有共用的逻辑和布局,比如菜单。所以可以把父页面、子页面当做没有关联的独立的页面。
Vue Router 常规路由
常规的一级路由,路由信息:
{
path: '/home',
name: 'Home',
component: () => import('@/views/Home'),
},
{
path: '/page1',
name: 'Page1',
component: () => import('@/views/Page1'),
},
{
path: '/page2',
name: 'Page2',
component: () => import('@/views/Page2'),
},
父页面和子页面是同级的路由,它们在路由上没有嵌套的关系,这样是能实现页面跳转的。
Vue Router 二级嵌套路由
一般的嵌套路由是这样的:
{
path: '/home',
name: 'Home',
redirect: '/home/page1',
component: () => import('@/views/Home'),
children: [
{
path: 'page1',
name: 'Page1',
component: () => import('@/views/Home/Page1'),
},
{
path: 'page2',
name: 'Page2',
component: () => import('@/views/Home/Page2'),
},
],
},
它实现的效果是这样的:
子页面是父页面的一部分,需要在父页面写 <router-view />
引入子页面。
注意,以 / 开头的嵌套路径将被视为根路径。这允许你利用组件嵌套,而不必使用嵌套的 URL。
这里 children
里的 path
没有以 /
开头,得到的子页面路由就是:/home/page2
这样,如果以 /
开头,得到的页面路由就是:/page1
。
扁平的二级嵌套路由
官网介绍了一种忽略父路由组件的用法,用法如下:
const routes = [
{
path: '/admin',
children: [
{ path: '', component: AdminOverview },
{ path: 'users', component: AdminUserList },
{ path: 'users/:id', component: AdminUserDetails },
],
},
]
父路由不写 component
,子路由中 path 为空的路由组件就渲染了父路由,其他路由和正常的嵌套路由一样。
Vue router 会直接跳过父路由,不渲染任何父组件,只加载匹配的子路由组件。
这样的做的好处有:
- 组织路由结构:将具有公共路径前缀的路由分组在一起
- 公共配置:为一组路由(子路由)配置公共的功能(
meta
字段或导航守卫)
受这种用法的启发,我们前面问题的路由可以这样设置:
{
path: '/home',
children: [
{
path: '',
name: 'Home',
component: () => import('@/views/Home/Home'),
},
{
path: 'page1',
name: 'Page1',
component: () => import('@/views/Home/Page1'),
},
{
path: 'page2',
name: 'Page2',
component: () => import('@/views/Home/Page2'),
},
],
},
父页面并非没有任何内容,只是把父页面当成一个子页面,用子路由来渲染。这样相比一级路由能更好的组织路由结构,Home 中不用写 <router-view />
,父路由做的是逻辑分组,而不是 UI 分组,父路由实际上也是有子路由渲染的。
这种路由方法或许可以叫做无组件嵌套路由、或者逻辑嵌套路由、或者扁平的嵌套路由。
这样做的好处
难道这样组织路由的好处只是更好的组织路由路径,更像一个二级嵌套关系而已吗?其他的路由守卫什么的暂时用不到。
实际上,我的菜单数据需要根据路由信息生成,其中的二级菜单也有对应的处理。应用上面的写法,即使特殊形式的二级页面,也不需要修改对菜单的处理。如果是一级路由形式,则需要手动处理一级二级页面的对应关系,处理菜单数据生成、
总结
在 Vue Router 中,灵活的路由结构可以大大提升项目的可维护性和可扩展性。通过扁平的二级嵌套路由,我们能够更好地组织路由,同时保持页面的独立性。这种方式不仅简化了路由的管理,还使得菜单生成逻辑更加清晰。