文章

Vue3-VueRouter4多布局实现方案

Vue3+Vue Router4多布局实现方案

Vue3-VueRouter4多布局实现方案

Vue3+Vue Router4多布局实现方案

实现步骤

  1. 创建布局组件
    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>
  1. 配置路由元信息
    在路由配置中,通过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
  1. 动态加载布局组件
    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项目中灵活切换不同布局,满足多菜单结构的业务需求。

本文由作者按照 CC BY 4.0 进行授权