Skip to content

5. Nuxt 3 布局

5.1 布局概念

布局(Layouts)是 Nuxt 应用程序中的一个包装组件,可用于在多个页面之间共享通用的 UI 结构。布局通常用于放置导航栏、页脚等在多个页面中重复出现的元素。

在 Nuxt 3 中,布局文件需要放置在 layouts 目录下。

5.2 定义布局

5.2.1 默认布局

默认布局文件为 layouts/default.vue,它将自动应用到所有页面:

vue
<script setup lang="ts">
interface HeaderProps {
  title: string
}

const props = withDefaults(defineProps<HeaderProps>(), {
  title: '默认标题'
})
</script>

<template>
  <div>
    <header>
      <nav>
        <h1>{{ props.title }}</h1>
      </nav>
    </header>
    
    <main>
      <slot />
    </main>

    <footer>
      <!-- 页脚内容 -->
    </footer>
  </div>
</template>

5.2.2 自定义布局

你可以创建多个布局文件,例如 layouts/custom.vue

vue
<script setup lang="ts">
interface AsideMenu {
  id: number
  title: string
  path: string
}

const menuItems = ref<AsideMenu[]>([
  { id: 1, title: '菜单1', path: '/menu1' },
  { id: 2, title: '菜单2', path: '/menu2' }
])
</script>

<template>
  <div class="custom-layout">
    <aside>
      <template v-for="item in menuItems" :key="item.id">
        <NuxtLink :to="item.path">{{ item.title }}</NuxtLink>
      </template>
    </aside>
    <div class="content">
      <slot />
    </div>
  </div>
</template>

5.3 使用布局

5.3.1 在页面中使用布局

可以通过以下方式在页面中使用特定布局:

vue
<script setup>
definePageMeta({
  layout: 'custom'
})
</script>

<template>
  <div>
    <!-- 页面内容 -->
  </div>
</template>

5.3.2 动态切换布局

你可以根据条件动态切换布局:

vue
<script setup lang="ts">
type LayoutType = 'default' | 'custom'

const layout = ref<LayoutType>('default')

const changeLayout = (): void => {
  layout.value = layout.value === 'default' ? 'custom' : 'default'
}
</script>

<template>
  <div>
    <button @click="changeLayout">切换布局</button>
    <!-- 页面内容 -->
  </div>
</template>

5.4 布局示例

5.4.1 管理后台布局

vue
<script setup lang="ts">
interface MenuItem {
  id: number
  title: string
  path: string
  icon?: string
}

interface UserInfo {
  name: string
  avatar: string
  role: string
}

const menuItems = ref<MenuItem[]>([
  { id: 1, title: '仪表盘', path: '/admin/dashboard', icon: 'dashboard' },
  { id: 2, title: '用户管理', path: '/admin/users', icon: 'users' },
  { id: 3, title: '系统设置', path: '/admin/settings', icon: 'settings' }
])

const userInfo = ref<UserInfo>({
  name: '管理员',
  avatar: '/avatar.png',
  role: 'admin'
})
</script>

<template>
  <div class="admin-layout">
    <nav class="sidebar">
      <template v-for="item in menuItems" :key="item.id">
        <NuxtLink :to="item.path">
          <i v-if="item.icon" :class="item.icon" />
          {{ item.title }}
        </NuxtLink>
      </template>
    </nav>
    
    <div class="main-content">
      <header>
        <h1>管理后台</h1>
        <div class="user-info">
          <img :src="userInfo.avatar" :alt="userInfo.name">
          <span>{{ userInfo.name }}</span>
        </div>
      </header>
      
      <main>
        <slot />
      </main>
    </div>
  </div>
</template>

<style scoped>
.admin-layout {
  display: grid;
  grid-template-columns: 250px 1fr;
  min-height: 100vh;
}

.sidebar {
  background-color: #f4f4f4;
  padding: 1rem;
}

.main-content {
  padding: 1rem;
}
</style>

5.5 最佳实践

  1. 为不同类型的页面创建专门的布局
  2. 使用 CSS Grid 或 Flexbox 构建灵活的布局结构
  3. 考虑响应式设计,适配不同设备
  4. 合理使用插槽分发内容
  5. 保持布局组件的单一职责

5.6 注意事项

  • 布局文件必须包含 <slot /> 组件以显示页面内容
  • 布局切换时会触发组件重新渲染
  • 避免在布局中放置过多的业务逻辑
  • 建议使用 CSS Grid 或 Flexbox 构建布局结构

5.7 小结

Nuxt 3 的布局系统提供了一种优雅的方式来组织和复用页面结构。通过合理使用布局,可以显著提高开发效率和代码复用率。