Vue3+Vue Router4多布局实现方案
实现步骤
- 创建布局组件
在layouts目录下创建不同的布局组件,每个组件需包含<router-view>用于显示页面内容。
1
2
3
4
5
6
7
8
9
10
| <!-- layouts/DefaultLayout.vue -->
<template>
<div class="default-layout">
<header>默认头部</header>
<nav>默认导航菜单</nav>
<main>
<router-view />
</main>
</div>
</template>
|
1
2
3
4
5
6
7
8
9
| <!-- layouts/AdminLayout.vue -->
<template>
<div class="admin-layout">
<aside>管理侧边栏</aside>
<div class="content">
<router-view />
</div>
</div>
</template>
|
- 配置路由元信息
在路由配置中,通过meta字段指定每个路由使用的布局组件名称。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| // router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
component: () => import('@/views/Home.vue'),
meta: { layout: 'DefaultLayout' } // 默认布局
},
{
path: '/admin',
component: () => import('@/views/Admin.vue'),
meta: { layout: 'AdminLayout' } // 管理后台布局
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
|
- 动态加载布局组件
在App.vue中根据当前路由的meta.layout动态加载对应的布局组件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| <!-- App.vue -->
<template>
<component :is="layoutComponent">
<router-view />
</component>
</template>
<script>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import DefaultLayout from '@/layouts/DefaultLayout.vue'
import AdminLayout from '@/layouts/AdminLayout.vue'
export default {
components: { DefaultLayout, AdminLayout },
setup() {
const route = useRoute()
const layoutComponent = computed(() => {
return route.meta.layout || 'DefaultLayout' // 默认为DefaultLayout
})
return { layoutComponent }
}
}
</script>
|
或使用动态导入(推荐):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <script>
import { computed, defineAsyncComponent } from 'vue'
import { useRoute } from 'vue-router'
export default {
setup() {
const route = useRoute()
const layoutComponent = computed(() => {
const layout = route.meta.layout || 'DefaultLayout'
return defineAsyncComponent(() =>
import(`@/layouts/${layout}.vue`).catch(() =>
import('@/layouts/DefaultLayout.vue') // 回退默认布局
)
)
})
return { layoutComponent }
}
}
</script>
|
高级优化
- 自动注册布局组件
使用Vite的import.meta.glob或Webpack的require.context自动导入布局组件:
1
2
3
4
5
6
7
8
| // main.js
const app = createApp(App)
const layoutModules = import.meta.glob('@/layouts/*.vue')
Object.entries(layoutModules).forEach(([path, component]) => {
const componentName = path.split('/').pop().replace(/\.vue$/, '')
app.component(componentName, defineAsyncComponent(component))
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <!-- layouts/AdminLayout.vue -->
<script setup>
import { router } from '@/router'
import { computed } from 'vue'
const menuItems = computed(() => {
return router.getRoutes()
.filter(route => route.meta.showInMenu)
.map(route => ({
path: route.path,
title: route.meta.title
}))
})
</script>
|
1
2
3
4
5
6
7
| <template>
<transition name="fade" mode="out-in">
<component :is="layoutComponent">
<router-view />
</component>
</transition>
</template>
|
注意事项
- 组件命名规范:确保布局组件文件名与
meta.layout的值一致(如AdminLayout.vue对应meta: { layout: 'AdminLayout' })。 - 错误处理:动态导入时需处理组件不存在的情况,避免应用崩溃。
- 性能优化:若布局组件较多,考虑代码分割,利用动态导入实现按需加载。
通过以上方案,即可在Vue3项目中灵活切换不同布局,满足多菜单结构的业务需求。