Nuxt.jsではaxiosを利用することで外部からデータを取得することができます。外部からのデータ取得はアプリケーションを構築する上で表示に重要な部分なので本文書ではNuxt.jsにおけるaxiosの使い方とasyncDataの使い方について説明を行っています。

本文書の内容はルーティングやtitleタグの設定などNuxt.jsの基礎知識が必要となります。Nuxt.jsがわからない場合はまず下記の文書を読むことをおすすめします。

外部のサービスについて

axiosを使って外部からデータを取得するためにはサーバを準備する必要があります。今回は無料のJSONPlaceholderを利用します。axiosの基本的な操作については下記の文書が参考になります。

Axiosの利用方法

Nuxt.jsをインストールする際にモジュールの選択項目がありますがそこでaxiosを選択している場合はaxiosの追加のインストールは必要ありません。しかし今回はaxiosに注目しているためaxiosモジュールをインストールしていない状態から動作確認を行っていきます。

Nuxt.jsではaxiosは通常のaxiosとnuxt.js用のモジュールの@nuxtjs/axiosを利用することができます。どちらも同じaxiosですが、記述方法が異なります。

デフォルトでプログレスバーの表示を行うことができ、nuxt.config.jsファイルを使ってオプション設定を行うこともできます。

axiosの使用方法を確認した後に@nuxtjs/axiosの使用方法を確認していきます。

nuxt.jsのインストール時に選択してインストールされるaxiosは@nuxtjs/axiosです

axiosのインストール

npmコマンドを利用してaxiosのインストールを行います。


 $ npm install axios

記事データの取得と一覧表示

インストールが完了したらaxiosを使ってJSONPlaceholderからpostsデータの取得を行います。postsデータを取得するために以下のURLへアクセスします。


https://jsonplaceholder.typicode.com/posts
ブラウザでhttps://jsonplaceholder.typicode.com/postsにアクセスするとどのような情報が取得できるか確認することができます。

取得したpostsデータを表示させるページの作成を行います。pagesディレクトリの中にpostsディレクトリを作成して、その下にindex.vueファイルを作成します。

Nuxt.jsではpagesディレクトリの下にディレクトリやファイルを作成すると自動でルーティングの設定を行ってくれます。pages/postsの下にindex.vueを作成すると/posts/にアクセスがあればindex.vueファイルの内容が表示されます。

axiosを利用するためにはaxiosをimportする必要があります。axiosで取得したデータをv-forを使って展開します。


<template>
<div>
  <h1>記事一覧</h1>
  <ul>
    <li v-for="post in posts" :key=post.id>
        {{ post.title }}
    </li>
  </ul>
</div>
</template>

<script>
import axios from 'axios';

export default {
  data(){
    return {
      posts: []
    }
  },
  mounted(){
    axios.get('https://jsonplaceholder.typicode.com/posts')
          .then(response => this.posts = response.data);
  }
}
</script>

ブラウザで確認すると記事一覧が表示されます。

axiosで記事一覧取得
axiosで記事一覧取得

記事の個別ページの取得

次は記事の個別ページの情報を取得します。アクセスするURLは下記の通りです。

postsの後ろの記事IDは1だけではなく2, 3,…記事の数だけ存在します。


https://jsonplaceholder.typicode.com/posts/1

記事数だけ個別ページを作成するのではなく1つのページを作成しそのページ共有して利用します。URLに含まれる記事IDによってサーバから取得する記事データが異なります。そのためURLに含まれる数字または文字列を取得する必要があります。

postsディレクトリの下に_id.vueファイルを作成します。_id.vueファイルという名前をつけた場合はpostsの後ろの数字はthis.$route.params.idで取得することができます。

idではなく_postId.vueとした場合はthis.$route.parames.postIdでURLに含まれる数字または文字を取得することができます。名前は任意の名前をつけることができます。

Nuxt.jsではheadプロパティを使うことで各ページにtitleやmetaタグの情報を追加することができます。headプロパティを利用してtitleを設定します。titleはページ毎に異なるため、取得したpostデータのtitleを利用します。


<template>
<div>
  <h1>記事個別ページ{{ post.id }}</h1>
  <h2>{{ post.title }}</h2>
  <p>{{ post.body}}</p>
</div>
</template>

<script>
import axios from 'axios';

export default {
  head(){
    return {
      title: this.post.title
    }
  },
  data(){
    return {
      post: {},
    }
  },
  mounted(){
    axios.get('https://jsonplaceholder.typicode.com/posts/' + this.$route.params.id)
          .then(response => this.post = response.data);
  }
}
</script>

ブラウザで確認すると個別ページの情報が表示されます。

記事の個別ページ
記事の個別ページ

ブラウザの表示では問題はありませんが、ブラウザからページのソースを確認するとtitleタグにはデフォルトの値が入っており_id.vueで設定したpost.titleは入っていません。

titleのデフォルトの値はnuxt.config.jsファイルのheadプロパティに記述されています。

この原因はNuxt.jsのmodeがSever Side Rendering(SSR)機能によりサーバ側でheadが設定されるためです。そのためライフサイクルフックのmountedの処理(ブラウザ側で行われる処理)でpostデータが取得できてもheadを設定することができません。この問題を解決するためにサーバ側でpostデータを取得する処理を行う仕組みが必要になります。

Nuxt.jsではサーバ側で処理を行うためにasyncDataが準備されています。

まずasyncDataの使用方法を確認し、その後にheadへの値の反映について説明を行っていきます。

asyncDataの使用方法

サーバ側で実行される処理asyncDataの使い方を確認していきます。

asyncDataはサーバ側で行う処理なのでコンポーネントのdataプロパティの設定を行うことができます。asyncDataはページのコンポーネントがロードされる前に呼ばれ、asyncDataを使うと下記のようにtitleを設定することが可能です。


export default {
  asyncData(){
    return{
      title: '個別ページ'
    }
  },
  head(){
    return {
      title: this.title
    }
  },
  data(){
    return {
      post: {},
    }
  },
  mounted(){
    axios.get('https://jsonplaceholder.typicode.com/posts/' + this.$route.params.id)
          .then(response => this.post = response.data);
  }
}

asyncDataはサーバ側で実行されるので、ブラウザからページのソースを確認するとtitleに個別ページが入っていることが確認できます。

コンポーネントのdataプロパティと同様に扱えるのでtemplateタグの中に{{ title }}を追加すると”個別ページ”と表示されます。

asyncDataを利用してpostsデータ取得

asyncDataを利用してサーバ側でpostsデータの取得を行います。pages/postsディレクトリのindex.vueファイルでasyncDataを利用して記事一覧を取得します。

asyncDataを利用する前はpostsデータを取得し、表示させるためにはdataプロパティとmountedが必要でしたがどちらも削除することができます。取得したデータpostsはdataプロパティなのでそのままtemplateタグで使用することができます。


import axios from 'axios';

export default {
  asyncData() {
    return axios.get('https://jsonplaceholder.typicode.com/posts/')
                .then(response => {
                  return {
                    posts: response.data
                  }
                })
  },
  // data(){
  //   return {
  //     posts: []
  //   }
  // },
  // mounted(){
  //   axios.get('https://jsonplaceholder.typicode.com/posts')
  //         .then(response => this.posts = response.data);
  // }

async, awaitを利用してコードを書き換え

asyncとawaitを利用して先程のコードを書き換えることができます。実行してもブラウザ上の結果は変わりません。


async asyncData() {
  const response = await axios.get('https://jsonplaceholder.typicode.com/posts/')
  return { posts: response.data }
},

複数の場所からaxiosを使ってデータを取得する場合はasyncとawaitを利用することで下記のように記述することができます。


async asyncData() {
  const responsePost = await axios.get('https://jsonplaceholder.typicode.com/posts/')
  const responseUser = await axios.get('https://jsonplaceholder.typicode.com/users/')
  return { posts: responsePost.data, users:responseUser.data }
},

syncDataを利用して個別データを取得

個別データの場合はURLに入った記事のIDが必要になります。mountedを利用していた場合はthis.$route.params.idで取得することができましたがsyncDataではこの値を利用することはできません。syncDataではcontextを利用することでidを取得することができます。


async asyncData(context) {
  const response = await axios.get('https://jsonplaceholder.typicode.com/posts/' + context.params.id)
  return { post: response.data }
},

contextはconsole.log(context)で確認することも可能です。contextにはさまざまな値が入っていますがES6のDestructuringを利用して記述を短縮化することができます。


async asyncData( { params } ) {
  const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts/' + params.id)
  return { post: data }
},

記事データはサーバ側で取得しているので、mountedでデータを取得した時に設定できなかったheadのtitleも設定されていることも確認できます。

ソースからtitleの確認
ソースからtitleの確認

nuxtjs/axiosモジュールのインストール

次は@nuxtjs/axiosモジュールをインストールして動作確認を行います。

Nuxt.jsのインストール中にaxiosを選択すると@nuxtjs/axiosモジュールがインストールされます。

インストールはnpmコマンドを利用します。


$ npm install @nuxtjs/axios

インストール後nuxt.config.jsファイルにaxiosの情報を登録する必要があります。


  modules: [
    '@nuxtjs/axios',  
  ],

nuxtjs/axiosモジュールを利用したデータ取得

axios単体ではファイル毎にimportでaxiosを読み込んでいましたが、nuxtjs/axiosの場合はcontextを利用してaxiosを使います。

axiosの記述方法ですがaxios.getからcontext.$axios.$getに変更になります。context.$axios.$getに変更するとresponseではなく直接response.dataが戻されます。


async asyncData(context) {
  const posts = await context.$axios.$get('https://jsonplaceholder.typicode.com/posts/')
  return { posts }
},
$getではなくgetにするとresponseが戻されます。{ posts } は{ posts : posts }を短縮したものです。

contextをES6のDestructuringを利用して記述を短縮化することができます。


async asyncData({$axios}) {
  const posts = await $axios.$get('https://jsonplaceholder.typicode.com/posts/')
  return { posts }
},

nuxtjs/axiosを利用したプログレスバーの設定

nuxtjs/axiosではデフォルト設定のままプログレスバーを表示させることができます。

プログレスバーはページを移動する際に移動先のページが表示されるまで上部に表示されます。デフォルトでも設定されているのですが、colorが#fff(白)のため背景に隠れて存在を確認することができません。nuxt.config.jsファイルで色の設定を変更します。


  ** Customize the progress-bar color
  */
  loading: { color: '#FF8733' },
  /*

index.vueで取得した各記事にnext-linkタグをつけてリンクを貼ります。


<template>
<div>
  <h1>記事一覧</h1>
  <ul>
    <li v-for="post in posts" :key=post.id>
        <nuxt-link :to="'/posts/' + post.id">{{ post.title }}</nuxt-link>
    </li>
  </ul>
</div>
</template>

記事のリンクボタンをクリックすると個別ページが表示される前に上部にプログレスバーが表示されることを確認できます。

nuxtjs/axiosのオプションの設定

nuxtjs/axiosでオプションの設定をnuxt.config.jsファイルで行うことができます。Nuxt.jsを使ってインストールをした場合に下記は自動でnuxt.config.jsファイルに存在しますが、Nuxt.jsのインストールとは別にnuxtjs/axiosをインストールした場合は追加する必要があります。


  modules: [
    '@nuxtjs/axios',  
  ],
  /*
  ** Axios module configuration
  ** See https://axios.nuxtjs.org/options
  */
  axios: {
  },

一番簡単なbaseURLを設定して動作確認を行ってみましょう。

baseURLでURLを登録しておくとこれまでhttps://jsonplaceholder.typicode.com/posts/と記述していましたが、/posts/のみの記述で問題ありません。


  axios: {
    baseURL: 'https://jsonplaceholder.typicode.com/'
  },

nuxt.config.jsを更新したのでindex.vueのURLを変更することができます。


async asyncData(context) {
  const posts = await context.$axios.$get('/posts/')
  return { posts }
},

変更しても表示される内容は変化はありません。