nuxt.svg

【Nuxt 2】ページとレイアウト

Nuxt2

ページの基本

NuxtJS では、ページも 1 つのコンポーネントとして考えられます。 そのため、ページは単一ファイルコンポーネントとして作成します。

ページは特別に/pagesフォルダが用意されており、ここにページのファイルを配備します。 詳細は別の記事で説明しますが、/pagesフォルダの構成によってルーティングが決まります。 NuxtJS では重要なことなので、覚えておきましょう。

ライフサイクル

ページはコンポーネントではありますが、通常のコンポーネントのライフサイクルの前にmiddlewareasyncDataという処理が順に実行されます。

この 2 つの処理はページ専用であり、ページ遷移の度に実行されます。

middleware

middlewareは、ページがレンダリングされる前に実行したい処理を定義します。 例えば、ページ遷移の前に認可処理を行うなどといった目的で使用します。

処理の定義は/middlewareフォルダに js ファイルを作成して行います。 middlewareの処理では、contextというオブジェクトを参照します。 これについては後述します。

/middleware/hoge.js
export default function(context) {
  //実行したい処理
}

作成したmiddlewareは、ページのmiddlewareプロパティで読み込むことで実行されるようになります。

Page
export default {
  middleware: 'hoge'
}

またすべてのページに適用する場合は、以下のようにnuxt.config.jsに設定を追記します。

nuxt.config.js
export default {
  router: {
    middleware: 'hoge'  //複数設定する場合は['hoge', 'fuga']のように設定
  }
}

asyncData

asyncDataは、ページのレンダリングの前に外部からデータを取得する目的で使用します。 取得したデータはreturnすることで、create時にdataプロパティへと反映されます。

export default {
  asyncData(context) {
    //API接続は仮のメソッドです
    const user = get('url')
    return {
      user: data.user,
    }
  },
  computed: {
    userName() {
      return this.user.name
    },
  },
}

asyncDatamiddleware同様、contextを参照します。

fetch

fetchについては、NuxtJS 2.12 以降で仕様が変わります。

NuxtJS 2.12 未満では、asyncDataと同様ページ専用の処理で、外部からデータを取得してストアに反映することが目的でした。

しかし、NuxtJS 2.12 以降では、すべてのコンポーネントで実行されます。 beforeMountの前に実行され、外部からデータを取得する目的で使用されます。

詳細については割愛しますが、仕様が違うことに注意しましょう。

context

例えば、コンポーネント内でルーティング情報を参照するには、this.$routeとします。 thisとは、Vue インスタンスのことであり、createのライフサイクルによって生成されます。

しかし、middlewareasyncDataは、Vue インスタンスが生成される前に実行されるため、this.$routeのような参照はできません。 そこで代わりの役割を担うのがcontextオブジェクトです。

contextオブジェクトは、Vue インスタンスに設定される以下の情報を持ちます。

キー説明
appVue インスタンスのオプション
storeストア情報
routeルーティング情報(パスなど)
paramsパスパラメーター(route.params
queryクエリパラメーター(route.query
env環境変数
redirect()他ページへのリダイレクト処理
error()エラーページの表示処理

contextを使用する場合は、基本的には必要なプロパティのみを指定します。 下記は、クエリパラメーターを参照し、該当の情報がなければエラー画面を表示する、といった例です。

export default {
  asyncData({ query, error }) {
    if (!query.id) {
      error({ statusCode: 400, message: 'Bad Request' })
    }
  },
}

ページプロパティ

ページには、通常のコンポーネントにはない特別なプロパティを持ちます。 先程のmiddlewareasyncDataもページプロパティとして設定します。

headは、ページのメタ情報など<head>の内容を設定します。 主にタイトルや OGP の情報を動的に設定するために使用します。

ページ共通の<head>nuxt.config.jsに設定します。

export default {
  head() {
    return {
      title: 'ページタイトル',
      meta: [
        {
          hid: 'description',
          name: 'description',
          content: 'ページの詳細情報',
        },
      ],
    }
  },
}
結果
<head>
  <title>ページタイトル</title>
  <meta data-hid="description" name="description" content="ページの詳細情報">
</head>

transition

transitionプロパティは、ページ遷移時にアニメーションを設定するために使用します。 すべてのページに<transition>が埋め込まれていると考え、transitionプロパティでnameディレクティブを指定します。

イメージ
<transition name="fade-page">
  <page-component />
</transition>

以下が設定例です。

export default {
  transition: 'fade-page',
}
.fade-page-enter-active {
  transition: opacity 1s;
}
.fade-page-enter {
  opacity: 0;
}

scrollToTop

ページを表示した際に、スクロールを最上部に戻すかをBooleanで指定します。

export default {
  scrollToTop: true,
}

レイアウト

レイアウトは、例えばヘッダーやフッターなどページの共通部分を定義するためのものです。 ページと同様単一コンポーネントで作成し、/layoutsフォルダに配備します。

<template>
  <div>
    <header>Header</header>
    <main>
      <nuxt />
    </main>
    <footer>Footer</footer>
  </div>
</template>

レイアウトには、必ず<nuxt />を指定してください。 ここにページの内容が展開されます。

すべてのページは、デフォルトで/layouts/default.vueをレイアウトとして使用します。 別のレイアウトを使用する場合は、ページのlayoutプロパティにレイアウト名(ファイル名)を指定します。

export default {
  // /layouts/sample.vueの読み込み
  layout: 'sample',
}

エラーページ

エラーページは、/layoutsフォルダにerror.vueというファイルとして作成します。 エラーの情報は、errorプロパティとして受け取ります。

error.vue
<template>
  <div>
    <h1>Error Page</h1>
    <p>status code: {{ error.statusCode }}</p>
    <p>message: {{ error.message }}</p>
  </div>
</template>

<script>
export default {
  props: ['error']
}
</script>

例えば、存在しないパスにアクセスした場合にエラーページが表示されます。

ページ内では、以下のようにthis.$error()とすることでエラーページを表示できます。

this.$error({ statusCode: 400, message: 'hogehoge' })

middlewareasyncDataなど、contextを使用する場合は以下のようにすることで、エラーページを表示します。

asnycData({ error }) {
  //...
  error({statusCode: 400, message: 'hogehoge'})
}