Vue:axiosとvue-cliを使ったAPI呼び出し
Vue:axiosとvue-cliを使ったAPI呼び出し
Vueで使える、PromiseベースのHTTPクライアント axios のインストールからAPI呼び出しまでを、vue-cliを使ってやります。
インストール
npm install axios vue-axios
Vue CLIのプロジェクト作成
VueCLIインストール
インストールコマンド
npm install -g @vue/cli
インストール確認
vue --version
@vue/cli 4.5.11
プロジェクト新規作成
vue create testjs
いくつか候補が出てくるが、とりあえず「Default ([Vue 2] babel, eslint)」を選んだ。
ホットリロード環境起動
cd testjs npm run serve
API呼び出し
Bitcoinの価格を取得するCoinDeskAPIを呼んでみます。
APIの調査
まずエンドポイントのURLと、取得できるデータがどのようなものかを調べます。
coindesk
https://www.coindesk.com/coindesk-api
を読んでいくと、エンドポイントが以下のURLであることが分かりました。
https://api.coindesk.com/v1/bpi/currentprice.json
ひとまずブラウザで開いてみます。
Vueから呼び出し
main.jsを編集します。
- main.jsで
Vue.use()
グローバルメソッドを呼び出すことで、プラグインが使用できるようになります。必ずnew Vue()
の前に呼び出す必要があります。
import Vue from 'vue' import App from './App.vue' import axios from 'axios' //追加 import VueAxios from 'vue-axios' //追加 Vue.config.productionTip = false Vue.use(VueAxios, axios) //追加 new Vue({ render: h => h(App) }).$mount('#app')
App.vueにボタンとAPI呼び出しを行う処理を追加します。
- App.vue内にgetApiData()というAPIを呼び出すメソッドを追加
- Load APIボタンのクリックでそのメソッドを呼び出すようにしています
- 結果は、apidata変数に格納され、{{ apidata }}部分に反映されます
<template> <div id="app"> <button type="button" @click="getApiData">Load API</button> {{ apidata }} </div> </template> <script> export default { name: 'App', data () { return { apidata: '' } }, methods: { getApiData() { this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response)) } } } </script>
作成したボタンをクリックすると、API呼び出しが行われ、取得できたjsonフォーマットのデータが画面に表示されます。
{ "data": { "time": { "updated": "Jan 31, 2021 07:38:00 UTC", "updatedISO": "2021-01-31T07:38:00+00:00", "updateduk": "Jan 31, 2021 at 07:38 GMT" }, "disclaimer": "This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org", "chartName": "Bitcoin", "bpi": { "USD": { "code": "USD", "symbol": "$", "rate": "33,735.5254", "description": (続く)
メモ:
Vue.use()ではなく、インスタンスプロパティとしてprototypeに追加しても使えるようです。
Vue.prototype.$axios = axios;
this.$axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response))
jsonの整形
jsonデータはドット演算子で読める。また、受信したデータはresponse.data
に入っているようである。
this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response.data.time))
{ "updated": "Jan 31, 2021 07:39:00 UTC", "updatedISO": "2021-01-31T07:39:00+00:00", "updateduk": "Jan 31, 2021 at 07:39 GMT" }
あとは、欲しいデータをたどっていけばOK
<button type="button" @click="getApiData">Load API</button><br /> Bitcoin price : {{ usdrate }} ( {{ currency }} )
export default { name: 'App', data () { return { usdrate: '', currency: '' } }, methods: { getApiData() { this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => ( this.usdrate = response.data.bpi.USD.rate, this.currency = response.data.bpi.USD.code )) } } }
画面には以下のように表示された。
Bitcoin price : 33,793.7048 ( USD )
jsonデータの一覧表示
取得したデータを一覧表示する。
<button type="button" @click="getApiData">Load API</button><br /> <div v-for="currency in apidata" v-bind:key="currency" > {{ currency.description }} <span v-html="currency.symbol"></span> {{ currency.rate_float | currencydecimal }} </div>
methods: { getApiData() { this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response.data.bpi)) } }, filters: { currencydecimal (value) { return value.toFixed(2) } }
出力。
United States Dollar $ 33740.0195 British Pound Sterling ? 24618.7764 Euro ? 27798.1659
単にtemplate側にapidata.data.bpi.USD
と書いてしまうと、ページのロード直後はapidataにデータが入っていないためエラーとなる。
これを避けるために、axiosのthenメソッド内で値を抽出してやるか、上記の例のようにv-for
を使い、データがあるものについてfor文を回すようにしないと値が取得できない。
エラー処理
下記のようなエラーが発生する可能性がある。
エラーの例:
そこで、.catchメソッドを用いてエラーをキャッチする処理を書く。
this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response.data.bpi)) .catch(error => {console.log(error))
また、ユーザにエラー時メッセージを表示しておくとよい。
<section v-if="errored"> <p>Sorry, some error happened. Try again later.</p> </section> <section v-else> (データ表示タグ) </section>
return { errored: false }
.catch(error => { console.log(error) this.errored = true })
ロード中表示
API呼び出しに時間がかかる可能性があるため、データロード中は「Loading...」などと表示しておきたい。
loadingのような変数を用意し、trueを入れておき、v-ifで「Loading...」を表示。
ロード完了後にloading変数にfalseをセットするとよい。
<div v-if="loading"> <p>Loading...</p> </div> <div v-else v-for="currency in apidata" v-bind:key="currency" > {{ currency.description }} ... </div>
return { loading : true }
this.axios.get('https://api.coindesk.com/v1/bpi/currentprice.json') .then(response => (this.apidata = response.data.bpi)) .catch(error => { console.log(error) }) .finally(() => this.loading = false)