layouts

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

启用 布局

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

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

要使用某个布局:

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

默认 布局

添加一个 ~/layouts/default.vue

app/layouts/default.vue
<template>
  <div>
    <p>Some default layout content shared across all pages</p>
    <slot />
  </div>
</template>

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

命名 布局

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

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

pages/about.vue
<script setup lang="ts">
declare module 'nuxt/app' {
  interface NuxtLayouts {
    'custom': unknown
  }
}
// ---cut---
definePageMeta({
  layout: 'custom',
})
</script>
了解更多关于 definePageMeta 的信息。

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

app/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 > 4 X > Examples > Features > Layouts.

动态更改 布局

你也可以使用 setPageLayout 辅助函数来动态更改布局:

app/pages/index.vue
<script setup lang="ts">
declare module 'nuxt/app' {
  interface NuxtLayouts {
    'custom': unknown
  }
}
// ---cut---
function enableCustomLayout () {
  setPageLayout('custom')
}
definePageMeta({
  layout: false,
})
</script>

<template>
  <div>
    <button @click="enableCustomLayout">
      更新布局
    </button>
  </div>
</template>

你也可以通过在路由规则中使用 appLayout 属性为特定路由设置布局:

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // 为特定路由设置布局
    '/admin': { appLayout: 'admin' },
    // 为多个路由设置布局
    '/dashboard/**': { appLayout: 'dashboard' },
    // Disable layout for a route
    '/landing': { appLayout: false },
  },
})
这在你想在配置中集中管理布局,而不是在每个页面文件中管理,或者当你需要为没有对应页面组件的路由(如可能匹配多个路径的通配页)应用布局时特别有用。
Read and edit a live example in Docs > 4 X > Examples > Features > Layouts.

给布局传递 Props +4.4

你可以通过多种方式向布局传递 props。

通过 definePageMeta

使用对象语法为 layout 属性传递 props,直接从你的页面传递:

<script setup lang="ts">
definePageMeta({
  layout: {
    name: 'panel',
    props: {
      sidebar: true,
      title: 'Dashboard',
    },
  },
})
</script>
Props 会基于布局的 defineProps 完全类型化。你将会在编辑器中获得自动补全和类型检查。

通过 setPageLayout

你也可以在动态更改布局时,使用 setPageLayout 传递 props:

setPageLayout('panel', { sidebar: true, title: 'Dashboard' })

在单页上覆盖 布局

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

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

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

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