データの取得

Nuxt.js はコンポーネントの mounted() フックでデータを取得するような、クライアントサイドアプリケーションにおける従来の Vue のデータの取得パターンをサポートしています。しかしユニバーサルアプリケーションでは、サーバーサイドレンダリング中にデータをレンダリングするために Nuxt.js 特有のフックを使う必要があります。これによりすべての必要なデータと一緒にページをレンダリングすることができます。

Nuxt は非同期なデータを読み込むために 2 つのフックを提供しています:

  • fetch フック(Nuxt 2.12 以降)。 どのコンポーネントにでも配置することができ、(クライアントサイドレンダリング中の) 読み込み状態やエラーをレンダリングするショートカットを提供します。
  • asyncData フック。 ページ コンポーネントにのみ配置することができます。 fetch と異なり、クライアントサイドレンダリング中にローディングプレースホルダーを示しません: そのかわり、ルートナビゲーションが解決されるまでそれをブロックし、失敗するとエラーページを表示します。

Nuxt 2.12 未満においては、fetch フックは今日の asyncData と非常によく似た働きをします。この機能は後方互換性のためまだサポートされています: もし fetch()context オブジェクトを受け取っているなら、それは 「レガシー」 な fetch フックだと考えられます。この機能は非推奨なので、asyncData(context)middleware(context) を使用した無名ミドルウェア に置き換えてください。

これらのフックは、選択した あらゆるデータ取得ライブラリ で使用することができます。HTTP API へリクエストを送るために @nuxt/http@nuxt/axios を使用することをおすすめします。認証ヘッダーの設定のような、これらのライブラリのより詳しい情報はそれぞれのドキュメントで見つけることができるでしょう。

fetch フック

このフックは Nuxt 2.12 以降でのみ使用することができます。

fetch はサーバーサイドレンダリングではコンポーネントのインスタンスが作成されたとき、クライアントサイドでは遷移するときに呼び出されるフックです。fetch フックは解決される promise を(明示的に、または async/await を使って暗黙的に)返却するべきです:

  • 初期ページがレンダリングされる前のサーバー
  • コンポーネントがマウントされた後のクライアント

以下のプロパティを持つ $fetchState をコンポーネントレベルで公開します:

  • pendingfetchクライアントサイド で呼び出されたときにプレースホルダーを表示するかを表す Boolean です。
  • errornull もしくは fetch フックからスローされた Error です。
  • timestamp は最後に fetch したタイムスタンプです。keep-alive でのキャッシング に便利です。

Nuxt が呼び出す fetch に加え、this.$fetch() を使うことでコンポーネント内から手動で fetch を呼び出すことができます。

components/NuxtMountains.vue
<template>
  <p v-if="$fetchState.pending">Fetching mountains...</p>
  <p v-else-if="$fetchState.error">An error occured :(</p>
  <div v-else>
    <h1>Nuxt Mountains</h1>
    <ul>
      <li v-for="mountain of mountains">{{ mountain.title }}</li>
    </ul>
    <button @click="$fetch">Refresh</button>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        mountains: []
      }
    },
    async fetch() {
      this.mountains = await fetch(
        'https://api.nuxtjs.dev/mountains'
      ).then(res => res.json())
    }
  }
</script>

fetch フック内では this.$nuxt.context を使うことで、Nuxt context にアクセスできます。

オプション

fetchOnServerBoolean または Function (デフォルト: true)。サーバーがページをレンダリングする際に fetch() を呼び出します。

fetchDelayInteger (デフォルト: 200)。最小実行時間をミリ秒単位で設定します(過剰実行を防ぐため)。

fetchOnServer が falsy (false または false を返す)な場合、fetch はクライアントサイドでのみ呼び出され、サーバーでコンポーネントをレンダリングする場合は、$fetchState.pendingtrue を返します。

export default {
  data() {
    return {
      posts: []
    }
  },
  async fetch() {
    this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
      res.json()
    )
  },
  // クライアントサイドでのみ fetch を呼び出します
  fetchOnServer: false
}

クエリ文字列の変化のリスニング

デフォルトでは、クエリ文字列の変化で fetch フックは呼び出されません。クエリ文字列の変化を監視するには、ウォッチャに $route.query を追加して $fetch を呼び出します:

export default {
  watch: {
    '$route.query': '$fetch'
  },
  async fetch() {
    // クエリ文字列の変化時にも呼び出される
  }
}

キャッシング

<nuxt/><nuxt-child/> コンポーネントで keep-alive ディレクティブを使うと、すでに訪れたページの fetch 呼び出しを保存することができます:

layouts/default.vue
<template>
  <nuxt keep-alive />
</template>

また、<nuxt> コンポーネントへ keep-alive-props prop を渡すことで、<keep-alive> に渡す props を指定することもできます。

layouts/default.vue
<nuxt keep-alive :keep-alive-props="{ max: 10 }" />

ページコンポーネントを 10 ページ分だけメモリに保存します。

activated  フックを使う

最後に fetch を呼び出したときのタイムスタンプを this.$fetchState.timestamp から取得することができます(SSR も含む)。このプロパティを activated フックと組み合わせることで、fetch に 30 秒のキャッシュを追加することができます:

pages/posts/_id.vue
<template> ... </template>

<script>
  export default {
    data() {
      return {
        posts: []
      }
    },
    activated() {
      // 最後の fetch から30秒以上経っていれば、fetch を呼び出します
      if (this.$fetchState.timestamp <= Date.now() - 30000) {
        this.$fetch()
      }
    },
    async fetch() {
      this.posts = await fetch('https://api.nuxtjs.dev/posts').then(res =>
        res.json()
      )
    }
  }
</script>

最後の fetch の呼び出しが 30 秒以内であれば、同じページへの遷移で fetch は呼ばれません。

Async Data

asyncDatapages でのみ使用可能で、このフック内では this にアクセスすることはできません。

asyncData はユニバーサルなデータ取得のためのもうひとつのフックです。非同期な状態を保存するために、コンポーネントのインスタンスにプロパティをセットする(または Vuex アクションをディスパッチする)必要がある fetch とは異なり、asyncData は単にその返却された値をコンポーネントのデータにマージします。以下は @nuxt/http ライブラリを使った例です:

pages/posts/_id.vue
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.description }}</p>
  </div>
</template>

<script>
  export default {
    async asyncData({ params, $http }) {
      const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
      return { post }
    }
  }
</script>

fetch と異なり、asyncData フックから返却される promise はルートの遷移の間に解決されます。つまり、"loading placeholder" はクライアントサイドの遷移で表示されないということです(ただし読み込み中の状態をユーザーに示すために ローディングバー を使うことができます)。Nuxt は代わりに asyncData フックの終了を待ってから、次のページへ移動したりエラーページを表示したりします。

このフックはページレベルのコンポーネントのためだけに使うことができます。fetch と異なり、asyncData はコンポーネントインスタンス (this) にアクセスすることはできません。そのかわりに、context を引数として受け取ります。asyncData をデータの取得のために使うことができ、Nuxt.js は自動で返却されたオブジェクトをコンポーネントのデータとマージします。

今後の例では、API からのデータの取得におすすめの @nuxt/http を使用します。

クエリ文字列の変化のリスニング

デフォルトでは、クエリ文字列の変化で asyncData メソッドは呼び出されません。ページネーションコンポーネントを作成するときなどにこの挙動を変えたい場合は、ページコンポーネントの watchQuery プロパティを見るパラメータを設定することができます。

watchQuery プロパティについてより学び、利用可能な context 内のキーのリストを見てみましょう。

Contributors

間違いを見つけた、またはドキュメントに貢献したいですか? GitHub でこのページを編集する