layouts

Nuxt 提供了一个布局框架,用于将常见的 UI 模式提取为可重用的布局。
为了获得最佳性能,放置在此目录中的组件将在被使用时通过异步导入自动加载。

启用布局

通过在 app.vue 中添加 <NuxtLayout> 来启用布局:

app.vue
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

使用布局的方法:

  • 在页面中通过 definePageMeta 设置 layout 属性。
  • 设置 <NuxtLayout>name 属性。
布局名称会被规范化为 kebab-case,比如 someLayout 会变成 some-layout
如果没有指定布局,则会使用 layouts/default.vue
如果你的应用中只有一个布局,建议直接使用 app.vue
与其他组件不同,你的布局必须有一个单一根元素,以允许 Nuxt 在布局切换时应用过渡效果——且这个根元素不能是 <slot />

默认布局

添加一个 ~/layouts/default.vue

layouts/default.vue
<template>
  <div>
    <p>一些所有页面共用的默认布局内容</p>
    <slot />
  </div>
</template>

在布局文件中,页面内容会显示在 <slot /> 组件的位置。

命名布局

目录结构
-| layouts/
---| default.vue
---| custom.vue

然后你可以在页面中使用 custom 布局:

pages/about.vue
<script setup lang="ts">
definePageMeta({
  layout: 'custom'
})
</script>
了解更多关于 definePageMeta 的内容。

你也可以通过 <NuxtLayout>name 属性直接覆盖所有页面的默认布局:

app.vue
<script setup lang="ts">
// 你可能会根据 API 调用或登录状态选择布局
const layout = "custom";
</script>

<template>
  <NuxtLayout :name="layout">
    <NuxtPage />
  </NuxtLayout>
</template>

如果你的布局在嵌套目录中,布局名称将基于其自身的路径目录和文件名,重复的片段会被移除。

文件布局名称
~/layouts/desktop/default.vuedesktop-default
~/layouts/desktop-base/base.vuedesktop-base
~/layouts/desktop/index.vuedesktop

为清晰起见,建议布局文件名与其名称匹配:

文件布局名称
~/layouts/desktop/DesktopDefault.vuedesktop-default
~/layouts/desktop-base/DesktopBase.vuedesktop-base
~/layouts/desktop/Desktop.vuedesktop
Read and edit a live example in Docs > Examples > Features > Layouts.

动态切换布局

你也可以使用 setPageLayout 辅助函数动态切换布局:

<script setup lang="ts">
function enableCustomLayout () {
  setPageLayout('custom')
}
definePageMeta({
  layout: false,
});
</script>

<template>
  <div>
    <button @click="enableCustomLayout">更新布局</button>
  </div>
</template>
Read and edit a live example in Docs > Examples > Features > Layouts.

针对单页重写布局

如果你使用页面机制,你可以通过设置 layout: false 来完全控制布局,然后在页面内使用 <NuxtLayout> 组件。

<script setup lang="ts">
definePageMeta({
  layout: false,
})
</script>

<template>
  <div>
    <NuxtLayout name="custom">
      <template #header> 一些头部模板内容。 </template>

      页面其余内容
    </NuxtLayout>
  </div>
</template>
如果你在页面中使用 <NuxtLayout>,确保它不是根元素(或者禁用布局/页面过渡)。