【Nuxt.js】layouts/で共通レイアウトを管理する方法

JavaScript

こんにちは、かつコーチです。

前回はpages/ディレクトリのファイルベースルーティングを解説しました。

今回は、ヘッダーやフッターなど「全ページ共通の見た目」をまとめるlayouts/ディレクトリを扱います。

「ページごとに同じヘッダーをコピペしていませんか」という悩みを、この記事で解決します。

レイアウトとは?

なぜ共通レイアウトが必要なのか

レイアウトとは、複数のページで使い回す共通の枠組みのことです。

ヘッダー・フッター・サイドバーなどが代表例です。

レイアウトを使わないと、すべてのページに同じHTMLを書くことになります。

修正が発生したとき、全ページを1つずつ直す必要が出てきて非効率です。

Nuxtではlayouts/ディレクトリにファイルを置くだけで、この共通化が自動的に行えます。

app.vueとの関係

Nuxtプロジェクトのルートにはapp.vueというファイルがあります。

ここに<NuxtLayout>というコンポーネントを置くことで、レイアウト機能が有効になります。

<!-- app.vue -->
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

<NuxtPage />が各ページの中身、<NuxtLayout>がその外側の共通枠、という役割分担です。

基本の書き方

手順1:layouts/default.vueを作る

まずはlayouts/default.vueを作成します。

ファイル名をdefault.vueにすると、何も指定しなくてもこのレイアウトが自動適用されます。

<!-- layouts/default.vue -->
<script setup lang="ts">
const currentYear: number = new Date().getFullYear()
</script>

<template>
  <div class="app-layout">
    <header>
      <h1>かつコーチのサイト</h1>
    </header>

    <main>
      <slot />
    </main>

    <footer>
      <p>© {{ currentYear }} Katsu Coach</p>
    </footer>
  </div>
</template>

手順2:<slot/>にページの中身が入る

ポイントは<slot />です。

この位置に、各ページ(pages/配下のコンポーネント)の中身が差し込まれます。

headerfooterはそのまま固定表示され、<slot />の部分だけがページごとに切り替わるイメージです。

つまずきやすい設定・注意点

私が最初につまずいたのはapp.vueの書き忘れです。

layouts/default.vueを作っただけで満足してしまい、app.vue側に<NuxtLayout>を書いていませんでした。

その結果、レイアウトが一切反映されず「ヘッダーが出ない」と数十分悩みました。

layouts/を使うなら、app.vue<NuxtLayout><NuxtPage /></NuxtLayout>があるか、必ず確認しましょう。

よくあるつまずきポイント・エラー対処

レイアウト名の大文字小文字問題

もう1つ実際にハマったのが、レイアウトファイル名の付け方です。

❌ Before:ファイル名を大文字始まりにする

<!-- layouts/Admin.vue -->
<template>
  <div class="admin-layout">
    <slot />
  </div>
</template>
<script setup lang="ts">
definePageMeta({
  layout: "Admin", // 大文字始まりで指定
})
</script>

これを実行すると、期待した管理画面用レイアウトが適用されず、default.vueのままになってしまいました。

コンソールにエラーは出ないため、原因に気づくまで少し時間がかかりました。

✅ After:ファイル名・指定名ともにケバブケース(小文字+ハイフン)にする

<!-- layouts/admin.vue -->
<template>
  <div class="admin-layout">
    <slot />
  </div>
</template>
<script setup lang="ts">
definePageMeta({
  layout: "admin", // ファイル名と一致させる
})
</script>

Nuxtはレイアウトファイル名をケバブケースとして扱います。

AdminUser.vueのようなファイルはadmin-userとして登録されるため、指定側もこの表記に合わせる必要があります。

応用・一歩先の使い方

definePageMetaで複数レイアウトを切り替える

サイト内に「通常ページ用」と「管理画面用」など、複数のレイアウトを持たせることもできます。

各ページの<script setup>内でdefinePageMetaを使い、layoutプロパティを指定するだけです。

<!-- pages/admin/index.vue -->
<script setup lang="ts">
definePageMeta({
  layout: "admin",
})
</script>

<template>
  <div>
    <h2>管理画面トップ</h2>
  </div>
</template>

このページだけlayouts/admin.vueが使われ、他のページはdefault.vueのままになります。

setPageLayoutで動的に切り替える

ログイン状態などに応じて、実行時にレイアウトを切り替えたい場合はsetPageLayout関数が便利です。

<script setup lang="ts">
const isLoggedIn = ref<boolean>(true)

if (isLoggedIn.value) {
  setPageLayout("member")
}
</script>

definePageMetaが「静的な指定」なのに対し、setPageLayoutは条件分岐など「動的な切り替え」に向いています。

レイアウトを一切使わないページには、layout: falseを指定することも可能です。

まとめ

この記事のポイント

  • layouts/default.vueを作ると、何も指定しなくても共通レイアウトが自動適用される
  • app.vue<NuxtLayout><NuxtPage /></NuxtLayout>を書かないとレイアウトは反映されない
  • レイアウトファイル名はケバブケースで扱われるため、definePageMetaの指定名もそれに合わせる
  • 複数レイアウトはdefinePageMeta({ layout: '名前' })、動的な切り替えはsetPageLayoutを使う

次に読むべき記事

レイアウトの基本を押さえたら、次は[id].vueなどを使った動的ルートの書き方を学んでいきましょう。

→ 次の記事:動的ルート・ネストされたルートの書き方

タグ: Nuxt.js, 初心者向け, ルーティング

タイトルとURLをコピーしました