Nuxt.jsのasyncDataとfetchの使い方とその違いについて
Nuxt.jsのasyncDataとfetchの使い方とその違いについて紹介します。
Nuxt.jsのasyncDataとfetchとは
Nuxt.jsでサーバーサードレンダリングを利用する際に使うのが、asyncDataとfetchです。
createdなどではサーバーサイドではなく、クライアントサイドでのレンダリングになります。
クライアントサイドでのレンダリングではソースコードが中身がない状態になってしまうので、SEO的によくありません。
コンポーネントのデータをセットするまえに、サーバーサイドでレンダリングできるようにするために、asyncData()メソッドを使います。
asyncData() {
return {}
},
data()との違い
data()メソッドととてもよく似ていて、オブジェクトをリターンします。
data()メソッドとの違いは、asyncData()メソッドもfetch()メソッドも、pageコンポーネントが初期化される前に呼び出されるという点です。
そのため、SSR(サーバーサイドレンダリング)が必要なときに使われます。
asyncData()メソッドもfetch()メソッドも、バックエンドで処理されるデータや、setTimeoutのような非同期の処理をコンポーネントがロードされるたびに呼び出されます。
なお、data()メソッドを一緒に使うと、asyncData()のデータが上書きされてしまうので、一緒には使いません。
thisキーワードは使えない
asyncData()メソッド内ではthisキーワードはundefinedになり、思うように使えません。
なぜなら、asyncData()はVueコンポーネントが作られる前、つまりthisキーワードが作られる前に実行されるからです。
また、asyncの処理が終わったことをつげないと終了したページを返してエラーが出ます。
その代わり、第一引数にcontextオブジェクトを取り、そのcontextオブジェクト内に必要なパラメータがあり、あらゆる処理が可能になります。
Nuxt.jsのasyncDataとfetchの違い
asyncDataは、pageコンポーネントへデータを直接セットする際に使います。apiを叩いてデータを取得する場合に使います。
fetchは、Vuexのstoreからデータをセットする際に使います。
asyncData()の使い方
<template>
<div class="posts-page">
<PostList :posts="loadedPosts"/>
</div>
</template>
<script>
export default {
components: {
PostList,
},
asyncData(context) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
loadedPosts: [
{
id: "1",
title: "最初の投稿",
previewText: "プレビューのテキスト",
thumbnail:"サムネ"
},
{
id: "2",
title: "二回目の投稿",
previewText: "二回目のプレビューテキスト",
thumbnail:"サムネ"
}
]
});
}, 1000);
// reject(new Error())
})
.then(data => {
return data
})
.catch(e => {
context.error(e);
});
}
}</script>
fetch()の使い方
上とほとんど同じですが、データはstoreフォルダから取得してきます。
<script>
export default {
components: {
PostList,
},
// asyncData(context) {
fetch(context) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
loadedPosts: [
{
id: "1",
title: "最初の投稿",
previewText: "プレビューのテキスト",
thumbnail:"サムネ"
},
{
id: "2",
title: "二回目の投稿",
previewText: "二回目のプレビューテキスト",
thumbnail:"サムネ"
}
]
});
}, 1000);
// reject(new Error())
})
.then(data => {
// return data
context.store.commit('setPosts', data.loadedPosts)
})
.catch(e => {
context.error(e);
});
},
computed: {
loadedPosts() {
return this.$store.getters.loadedPosts
}
}
}
</script>
asyncDataの部分をfetchに変更した点と、then()メソッドの中ではdataではなく、storeから取得する必要があるので、commitを使います。
また、templateタグとの連携があるので、computedを使ってstoreのgettersを使う必要があります。