---
title: "layouts"
description: "Nuxt 提供了一个布局框架，用于将常见的 UI 模式提取为可重用的布局。"
canonical_url: "https://nuxt.zhcndoc.com/docs/3.x/directory-structure/layouts"
---
# layouts

> Nuxt 提供了一个布局框架，用于将常见的 UI 模式提取为可重用的布局。

::tip{icon="i-lucide-rocket"}
为了获得最佳性能，放置在此目录中的组件将在被使用时通过异步导入自动加载。
::

## 启用布局

将 [`<NuxtLayout>`](https://nuxt.zhcndoc.com/docs/3.x/api/components/nuxt-layout) 添加到 [`app.vue`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/app) 中即可启用布局：

```vue [app.vue]
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
```

使用布局的方法：

- 在页面中通过 [definePageMeta](https://nuxt.zhcndoc.com/docs/3.x/api/utils/define-page-meta) 设置 `layout` 属性。
- 设置 `<NuxtLayout>` 的 `name` prop。
- 在路由规则中设置 `appLayout` 属性。

::note
布局名称会被规范化为 kebab-case，比如 `someLayout` 会变成 `some-layout`。
::

::note
如果没有指定布局，则会使用 `layouts/default.vue`。
::

::important
如果你的应用中只有一个布局，我们建议改用 [`app.vue`](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/app)。
::

::important
与其他组件不同，你的布局必须有一个单一根元素，以允许 Nuxt 在布局切换时应用过渡效果——且这个根元素不能是 `<slot />`。
::

## 默认布局

添加一个 `~/layouts/default.vue`：

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

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

## 命名布局

```bash [目录结构]
-| layouts/
---| default.vue
---| custom.vue
```

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

```vue twoslash [pages/about.vue]
<script setup lang="ts">
declare module 'nuxt/app' {
  interface NuxtLayouts {
    'custom': unknown
  }
}
// ---cut---
definePageMeta({
  layout: 'custom',
})
</script>
```

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/directory-structure/pages#page-metadata"}
详细了解 `definePageMeta`。
::

你可以使用 [`<NuxtLayout>`](https://nuxt.zhcndoc.com/docs/3.x/api/components/nuxt-layout) 的 `name` 属性，直接为所有页面覆盖默认布局：

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

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

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

| 文件                                | 布局名称              |
| --------------------------------- | ----------------- |
| `~/layouts/desktop/default.vue`   | `desktop-default` |
| `~/layouts/desktop-base/base.vue` | `desktop-base`    |
| `~/layouts/desktop/index.vue`     | `desktop`         |

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

| 文件                                       | 布局名称              |
| ---------------------------------------- | ----------------- |
| `~/layouts/desktop/DesktopDefault.vue`   | `desktop-default` |
| `~/layouts/desktop-base/DesktopBase.vue` | `desktop-base`    |
| `~/layouts/desktop/Desktop.vue`          | `desktop`         |

::link-example{to="https://nuxt.zhcndoc.com/docs/examples/features/layouts"}
::

## 动态切换布局

你也可以使用 [`setPageLayout`](https://nuxt.zhcndoc.com/docs/3.x/api/utils/set-page-layout) 辅助函数动态更改布局：

```vue twoslash [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` 属性为特定路由设置布局：

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  routeRules: {
    // 为特定路由设置布局
    '/admin': { appLayout: 'admin' },
    // 为多个路由设置布局
    '/dashboard/**': { appLayout: 'dashboard' },
    // 禁用某个路由的布局
    '/landing': { appLayout: false },
  },
})
```

::tip
当你希望在配置中集中管理布局，而不是在每个页面文件中设置，或者需要为没有对应页面组件的路由（例如可能匹配许多路径的 catchall 页面）应用布局时，这非常有用。
::

::link-example{to="https://nuxt.zhcndoc.com/docs/examples/features/layouts"}
::

## 针对单页重写布局

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

::code-group
```vue [pages/index.vue]
<script setup lang="ts">
definePageMeta({
  layout: false,
})
</script>

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

      页面其余内容
    </NuxtLayout>
  </div>
</template>
```

```vue [layouts/custom.vue]
<template>
  <div>
    <header>
      <slot name="header">
        默认头部内容
      </slot>
    </header>
    <main>
      <slot />
    </main>
  </div>
</template>
```
::

::important
如果你在页面中使用 `<NuxtLayout>`，请确保它不是根元素（或[禁用布局/页面过渡效果](https://nuxt.zhcndoc.com/docs/3.x/getting-started/transitions#disable-transitions)）。
::


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
