※ 環境
Nuxt 3.2.3
Node v18.11.0
複数ページで同じ UI を使う場合、各ページで同じコードを書いていたらプログラムの保守性が下がってしまいます。
そのようなケースを解消するために、Nuxt3 ではLayout
という機構が用意されています。
Layout の利用方法
Layout
を利用するには、
- Layout の UI を
layouts
ディレクトリに実装 - アプリケーションのメインコンポーネントである、
app.vue
を使っている場合はapp.vue
に<NuxtLayout>
を追加
する必要があります。
それぞれ見ていきましょう。
Layout の UI を layouts ディレクトリに実装する
まずはルートディレクトリ配下にlayouts
という名前のディレクトリを作成します。このディレクトリは Nuxt アプリケーション内で自動インポートされるため、import 構文を書かなくても読み込むことができるようになります。
ここで、layouts
ディレクトリにdefault.vue
という名前の Vue ファイルを作成しましょう。
layouts/default.vue
<template>
<header>Site name</header>
<main>
<slot />
</main>
</template>
default.vue
という名前で作成することで、アプリケーションのデフォルトレイアウトとなります。また、<slot />
は必ず書く必要があり、その中に page の DOM が挿入されます。
この時に、app.vue
を作成していない場合は、すでに全ページで default.vue のレイアウトが反映されていると思います。
app.vue がある場合は NuxtLayout を追加
メインコンポーネントのapp.vue
がある場合は、<NuxtLayout>
コンポーネントを追加する必要があります。
最小限の設定は、以下です。
app.vue
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
<NuxtPage />
にページの DOM が挿入されるため、その外側を<NuxtLayout />
で囲っています。こうすることで同様に全ページでdefault.vue
のレイアウトが反映されます。
ページによってレイアウトを変更させる
今までで、全てのページの共通レイアウトを設定することができました。しかし、ページによってはレイアウトを変更させたいケースがあると思います。
Nuxt は以下のようなユースケースに合わせた機能を用意しています。
ユースケース | 実現手段 |
---|---|
特定のページで別のレイアウトを使う | definePageMeta の layout プロパティでレイアウトを指定する |
特定のページでレイアウトを無効にする | definePageMeta の layout プロパティに false を設定する |
動的にレイアウトを切り替える | setPageLayout を使う |
それぞれのユースケースのコード例について見ていきましょう。
特定のページで別のレイアウトを使う
特定ページで別レイアウトを使うには、ページのメタデータを設定するdefinePageMeta
を利用します。
まず、切り替える用のレイアウトを作成します。ここでは、layouts/custom.vue
ファイルを用意します。
<template>
<header>Custom layout</header>
<main>
<slot />
</main>
</template>
利用する側のページでは、definePageMeta
でlayout
プロパティをlayouts
ディレクトリのファイル名に合わせます。
<script lang="ts" setup>
definePageMeta({
layout: "custom",
});
</script>
それによって、custom.vue
のレイアウトがこのページに反映されるようになります。
特定のページでレイアウトを無効にする
特定ページでレイアウトを無効にするには、definePageMeta
の layout プロパティにfalse
を設定します。
<script lang="ts" setup>
definePageMeta({
layout: false,
});
</script>
この場合はlayouts/default.vue
のレイアウトも反映されなくなります。
動的にレイアウトを切り替える
動的にレイアウトを切り替えたい場合は、setPageLayout
を使います。
setPageLayout
の引数にはlayouts
ディレクトリのファイル名を指定します。
以下例はボタンをクリックすることで、custom
レイアウトに切り替えています。
<script lang="ts" setup>
definePageMeta({
layout: false,
});
const setLayout = () => {
setPageLayout("custom");
};
</script>
<template>
<div>
<h1>test</h1>
<button @click="setLayout">Enable layout</button>
</div>
</template>