mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
181 lines
4.2 KiB
Markdown
181 lines
4.2 KiB
Markdown
---
|
|
title: "layouts"
|
|
head.title: "layouts/"
|
|
description: "Nuxt provides a layouts framework to extract common UI patterns into reusable layouts."
|
|
navigation.icon: i-ph-folder-duotone
|
|
---
|
|
|
|
::tip{icon="i-ph-rocket-launch-duotone" color="gray" }
|
|
For best performance, components placed in this directory will be automatically loaded via asynchronous import when used.
|
|
::
|
|
|
|
## Enable Layouts
|
|
|
|
Layouts are enabled by adding [`<NuxtLayout>`](/docs/api/components/nuxt-layout) to your [`app.vue`](/docs/guide/directory-structure/app):
|
|
|
|
```vue [app.vue]
|
|
<template>
|
|
<NuxtLayout>
|
|
<NuxtPage />
|
|
</NuxtLayout>
|
|
</template>
|
|
```
|
|
|
|
To use a layout:
|
|
- Set a `layout` property in your page with [definePageMeta](/docs/api/utils/define-page-meta).
|
|
- Set the `name` prop of `<NuxtLayout>`.
|
|
|
|
::note
|
|
The layout name is normalized to kebab-case, so `someLayout` becomes `some-layout`.
|
|
::
|
|
|
|
::note
|
|
If no layout is specified, `layouts/default.vue` will be used.
|
|
::
|
|
|
|
::important
|
|
If you only have a single layout in your application, we recommend using [`app.vue`](/docs/guide/directory-structure/app) instead.
|
|
::
|
|
|
|
::important
|
|
Unlike other components, your layouts must have a single root element to allow Nuxt to apply transitions between layout changes - and this root element cannot be a `<slot />`.
|
|
::
|
|
|
|
## Default Layout
|
|
|
|
Add a `~/layouts/default.vue`:
|
|
|
|
```vue [layouts/default.vue]
|
|
<template>
|
|
<div>
|
|
<p>Some default layout content shared across all pages</p>
|
|
<slot />
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
In a layout file, the content of the page will be displayed in the `<slot />` component.
|
|
|
|
## Named Layout
|
|
|
|
```bash [Directory Structure]
|
|
-| layouts/
|
|
---| default.vue
|
|
---| custom.vue
|
|
```
|
|
|
|
Then you can use the `custom` layout in your page:
|
|
|
|
```vue twoslash [pages/about.vue]
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: 'custom'
|
|
})
|
|
</script>
|
|
```
|
|
|
|
::read-more{to="/docs/guide/directory-structure/pages#page-metadata"}
|
|
Learn more about `definePageMeta`.
|
|
::
|
|
|
|
You can directly override the default layout for all pages using the `name` property of [`<NuxtLayout>`](/docs/api/components/nuxt-layout):
|
|
|
|
```vue [app.vue]
|
|
<script setup lang="ts">
|
|
// You might choose this based on an API call or logged-in status
|
|
const layout = "custom";
|
|
</script>
|
|
|
|
<template>
|
|
<NuxtLayout :name="layout">
|
|
<NuxtPage />
|
|
</NuxtLayout>
|
|
</template>
|
|
```
|
|
|
|
If you have a layout in nested directories, the layout's name will be based on its own path directory and filename, with duplicate segments being removed.
|
|
|
|
File | Layout Name
|
|
-- | --
|
|
`~/layouts/desktop/default.vue` | `desktop-default`
|
|
`~/layouts/desktop-base/base.vue` | `desktop-base`
|
|
`~/layouts/desktop/index.vue` | `desktop`
|
|
|
|
For clarity, we recommend that the layout's filename matches its name:
|
|
|
|
File | Layout Name
|
|
-- | --
|
|
`~/layouts/desktop/DesktopDefault.vue` | `desktop-default`
|
|
`~/layouts/desktop-base/DesktopBase.vue` | `desktop-base`
|
|
`~/layouts/desktop/Desktop.vue` | `desktop`
|
|
|
|
:link-example{to="/docs/examples/features/layouts"}
|
|
|
|
## Changing the Layout Dynamically
|
|
|
|
You can also use the [`setPageLayout`](/docs/api/utils/set-page-layout) helper to change the layout dynamically:
|
|
|
|
```vue twoslash
|
|
<script setup lang="ts">
|
|
function enableCustomLayout () {
|
|
setPageLayout('custom')
|
|
}
|
|
definePageMeta({
|
|
layout: false,
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<button @click="enableCustomLayout">Update layout</button>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
:link-example{to="/docs/examples/features/layouts"}
|
|
|
|
## Overriding a Layout on a Per-page Basis
|
|
|
|
If you are using pages, you can take full control by setting `layout: false` and then using the `<NuxtLayout>` component within the page.
|
|
|
|
::code-group
|
|
|
|
```vue [pages/index.vue]
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: false,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<NuxtLayout name="custom">
|
|
<template #header> Some header template content. </template>
|
|
|
|
The rest of the page
|
|
</NuxtLayout>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
```vue [layouts/custom.vue]
|
|
<template>
|
|
<div>
|
|
<header>
|
|
<slot name="header">
|
|
Default header content
|
|
</slot>
|
|
</header>
|
|
<main>
|
|
<slot />
|
|
</main>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
::
|
|
|
|
::important
|
|
If you use `<NuxtLayout>` within your pages, make sure it is not the root element (or [disable layout/page transitions](/docs/getting-started/transitions#disable-transitions)).
|
|
::
|