データの取得
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
をコンポーネントレベルで公開します:
pending
はfetch
が クライアントサイド で呼び出されたときにプレースホルダーを表示するかを表すBoolean
です。error
はnull
もしくは fetch フックからスローされたError
です。timestamp
は最後に fetch したタイムスタンプです。keep-alive
でのキャッシング に便利です。
Nuxt が呼び出す fetch に加え、this.$fetch()
を使うことでコンポーネント内から手動で fetch を呼び出すことができます。
<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 にアクセスできます。
オプション
fetchOnServer
: Boolean
または Function
(デフォルト: true
)。サーバーがページをレンダリングする際に fetch()
を呼び出します。
fetchDelay
: Integer
(デフォルト: 200
)。最小実行時間をミリ秒単位で設定します(過剰実行を防ぐため)。
fetchOnServer
が falsy(false
または false
を返す)な場合、fetch
はクライアントサイドでのみ呼び出され、サーバーでコンポーネントをレンダリングする場合は、$fetchState.pending
は true
を返します。
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
呼び出しを保存することができます:
<template>
<nuxt keep-alive />
</template>
また、<nuxt>
コンポーネントへ keep-alive-props
prop を渡すことで、<keep-alive>
に渡す props を指定することもできます。
<nuxt keep-alive :keep-alive-props="{ max: 10 }" />
ページコンポーネントを 10 ページ分だけメモリに保存します。
activated
フックを使う
最後に fetch
を呼び出したときのタイムスタンプを this.$fetchState.timestamp
から取得することができます(SSR も含む)。このプロパティを activated
フックと組み合わせることで、fetch
に 30 秒のキャッシュを追加することができます:
<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
asyncData
は pages でのみ使用可能で、このフック内では this
にアクセスすることはできません。
asyncData
はユニバーサルなデータ取得のためのもう 1 つのフックです。非同期な状態を保存するために、コンポーネントのインスタンスにプロパティをセットする(または Vuex アクションをディスパッチする)必要がある fetch
とは異なり、asyncData
は単にその返却された値をコンポーネントのデータにマージします。以下は @nuxt/http ライブラリを使った例です:
<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 内のキーのリストを見てみましょう。