Vue.js

Nuxt.jsで複数のlayoutsファイルを作成して適用する方法

Nuxt.jsで複数のlayoutsファイルを作成して適用する方法を紹介します。layouts/に新しいVueファイルを置き、ページ側でlayoutプロパティ(Nuxt 3ならdefinePageMeta)を指定するだけで切り替えられます。

この記事の目次
  1. Nuxt.jsで複数のlayoutsファイルを作成して適用する方法
  2. 新しいレイアウトを作成する
  3. 作成したレイアウトを適用する
  4. Nuxt 3での書き方

Nuxt.jsで複数のlayoutsファイルを作成して適用する方法を紹介します。

Nuxt.jsで複数のlayoutsファイルを作成して適用する方法

手順は2つです。layouts/ に新しいVueファイル(例: products.vue)を置き、それを使いたいページ側で layout: 'products' と指定します。ファイル名がそのままレイアウト名になり、指定しないページには default.vue が使われます。
この記事のコードはNuxt 2のものです。Nuxt 3での書き方は最後にまとめています。
Nuxt.jsで複数のlayoutsを使う方法
ディレクトリ構造は上のようになっているとします。

手順は次の通りです。

  1. layoutsフォルダの中に、新しいVueファイルを作成します。
  2. そして、それをpagesのファイルでNuxt.jsの特別なプロパティであるlayoutプロパティを使って指定します。

具体例をみてみましょう。

まずデフォルトで設定されているlayoutsのdefault.vueは次のような内容になっています。

<template>
  <div>
    <Nuxt />
  </div>
</template>

ここに、styleタグでスタイルを設定しています。
Nuxtの部分に各ページの内容が出力されます。

何も指定しない限り、ここで指定されているレイアウトが適用されます。

複数レイアウトを作成して、個別のケースでレイアウトを使い分けたい場合は、layoutsフォルダの中にVueファイルを作成します。

今回の場合、products.vueファイルを作成しています。

新しいレイアウトを作成する

layouts/products.vue

<template>
  <div>
    <header>商品ページ</header>
    <Nuxt />
  </div>
</template>

ここにstyleを指定すればレイアウトを整えられます。レイアウト共通のCSSをまとめて読み込みたい場合はNuxt.jsでassetsのcssをグローバルに適用する方法を参考にしてください。

そして、このレイアウトを適用させるためには、layoutプロパティを使います。

作成したレイアウトを適用する

pages/products.vueに適用したいとします。
その場合、次のようにscriptタグの中で、layoutプロパティを使います。

<script>
export default {
  data() {
    return {
      productId: ''
    }
  },
  methods: {
    onLoadProduct() {
      this.$router.push(`/products/${this.productId}`)
    }
  },
  layout: 'products'
}</script>

また、ネストしている場合は、このレイアウトを適用したいすべてのVueファイルに同じようにlayoutプロパティでレイアウトを指定すればOKです。
レイアウトはページの外側を担当するだけなので、全ページで先に用意しておきたいデータ(ログインユーザーなど)はレイアウトではなくnuxtServerInit側で用意します。

Nuxt 3での書き方

Nuxt 3では、レイアウトの仕組みは同じですが、書き方が3か所変わります。

  • レイアウト内でページを出す場所は <Nuxt /> ではなく <slot />
  • app.vue<NuxtLayout><NuxtPage /></NuxtLayout> を書いてレイアウトを有効にする
  • ページ側の指定は layout: 'products' ではなく definePageMeta({ layout: 'products' })
<!-- layouts/products.vue -->
<template>
  <div>
    <header>商品ページ</header>
    <slot />
  </div>
</template>

<!-- pages/products.vue -->
<script setup>
definePageMeta({ layout: 'products' })
</script>
スポンサーリンク