Nuxt.jsのasyncDataとfetchの使い方とその違いについて

Vue.js

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を使う必要があります。

Vue.js

Posted by devsakaso