Layoutを使ってページ間で共通のUIを利用する【Nuxt3】

Posted: 2023/3/13
Nuxt.js/
Page
※ 環境
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>

利用する側のページでは、definePageMetalayoutプロパティを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>