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>所有页面共享的默认布局内容</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>

你也可以在 route rules 中使用 appLayout 属性为特定路由设置布局 v4.3:

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

Passing Props to Layouts +4.4

You can pass props to layouts in several ways.

Via definePageMeta

Pass props to the layout property using object syntax, directly from your page:

<script setup lang="ts">
definePageMeta({
  layout: {
    name: 'panel',
    props: {
      sidebar: true,
      title: 'Dashboard',
    },
  },
})
</script>
Props are fully typed based on the layout's defineProps. You'll get autocomplete and type checking in your editor.

Via setPageLayout

You can also pass props when changing layouts dynamically, using setPageLayout:

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>,请确保它不是根元素(或禁用 布局/页面 过渡)。