Vue.js/Nuxt.jsでHTTP非同期通信axios/asyncDataを使ってみる

★axiosは非同期処理オブジェクトPromiseベースのHTTPクライアントで簡単にHTTPアクセスできるよ。
★asyncDataメソッド
・ページコンポーネントがロードされるたびに呼ばれる。
・data()の前に非同期処理でdataとマージされるのでここでセットされるデータはdata()で初期設定とかしなくてもエラーにならない。

インストール

C:\vue\nuxt-sample>npm install axios

サーバ側サンプル

GETメソッドでidが来たら都道府県名をjsonで返すよ!

http://vue.localhost/pref.php

<?php
$prefList = [
	1 => '北海道',
	2 => '青森県',
	3 => '岩手県',
	4 => '宮城県',
	5 => '秋田県',
	
];

$res['status'] = 200;
$res['prefecture'] = 'No Data...';
if (isset($_GET['id']) && isset($prefList[$_GET['id']])) {
	$res['prefecture'] = $prefList[$_GET['id']];
}
echo json_encode($res);

page作成

上記サンプルページにアクセスして都道府県名を取得して表示するよ。

page/pref.vue

<template>
  <section class="container">
    <h2>都道府県</h2>
    <div>{{ pref }}</div>
  </section>
</template>

<script>
import axios from 'axios'

export default {
  // Promiseを返す方法
  asyncData ({ query }) {
    return axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
    .then((res) => {
      return { pref: res.data.prefecture }
    })
  }
}
</script>

http://localhost:3000/pref/?id=1

3種類のasyncDataメソッドの使い方

【Promiseを返す】
※上記の方法

  asyncData ({ query }) {
    return axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
    .then((res) => {
      return { pref: res.data.prefecture }
    })
  }

【async/awaitを使う】

  async asyncData({ query }) {
    let { data } = await axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
    return { pref: data.prefecture };
  }

【コールバックを定義する】

  asyncData ({ query }, callback) {
    axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
    .then((res) => {
      callback(null, { pref: res.data.prefecture })
    })
  }

asyncDataメソッドの引数

asyncDataメソッドの引数はコンテキストだよ。

今回はQueryStringが欲しかったから
query:route.queryのエリアス
を設定したけど他に使うとしたら・・・

params:route.paramsのエリアス(動的ルーティング時のURLのpathとか?
error:エラー処理(後述)
store:Vuexのストアオブジェクト
app:ルートVueインスタンス(全部入り?

参照:https://ja.nuxtjs.org/api/context

カンマ区切りで複数設定できるみたいね。

asyncData ({ query, params })

※いろんなサイトで使い方の例を見てみたけどほとんど「params」だったので当然取得できません。
QueryStringの値ってどうやってとるのよ?コンテキストってなんなのよ~?
ってだいぶ悩んだのはヒミツw

※そういえば、動的ルーティングのところで
this.$route.params.id
って魔法の言葉「params」が出てきてたね!

【動的ルーティングの場合】

pages/pref/_id.vue

  asyncData ({ params }) {
    return axios.get(`http://vue.localhost/pref.php?id=${params.id}`)
    .then((res) => {
      return { pref: res.data.prefecture }
    })
  }

queryをparamsに変えるだけでOK!

http://localhost:3000/pref/[id]

エラー処理

【Promiseを返す場合】

  asyncData ({ query, error }) {
    return axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
    .then((res) => {
      return { pref: res.data.prefecture }
    })
    .catch((e) => {
      error({ statusCode: 404, message: 'ページが見つかりません' })
    })
  }

【async/awaitを使う場合】

  async asyncData({ query, error }) {
    try {
      let { data } = await axios.get(`http://vue.localhost/pref.php?id=${query.id}`)
      return { pref: data.prefecture };
    } catch(e) {
      error({ statusCode: 404, message: 'ページが見つかりません' })
    }
  }

【コールバックを定義する場合】

  asyncData ({ query }, callback) {
    axios.get(`http://vue.localhost/pref1.php?id=${query.id}`)
    .then((res) => {
      callback(null, { pref: res.data.prefecture })
    })
    .catch((e) => {
      callback({ statusCode: 404, message: 'ページが見つかりません' })
    })
  }

※やり方は【Promiseを返す場合】と同じだけど引数にerrorは要らないのね。