api
Vue.js
axios
nuxt.js

【Nuxt.js】郵便番号検索APIを使ってデータ取得を学ぶ

ちゃんと理解できていなかった、「APIを使ってデータ取得する」ことについてまとめました。

APIからデータを取ってきて何かアプリを作ってみたいという方や、

Nuxt.jsでのデータ取得についても書いているので、Nuxt.jsを勉強している方にも読んでもらえると嬉しいです。


今回作成したもの

スクリーンショット 2019-04-11 19.25.31.png

住所入力フォームでよくある、

郵便番号を入力してボタンを押したら自動で住所を入力してくれるプログラムです。

郵便番号検索APIは登録不要ですぐに使えます。


前提

・Node.jsはインストール済(バージョンは現時点でv10.13.0)

・Vue.js/Nuxt.jsはある程度理解している

(私はVue.js & Nuxt.js超入門で勉強していました。また、こちらの記事も参考にしていただければと思います。)


作成の手順


  1. Nuxt.jsのプロジェクトを作成する

  2. templateを作成する

  3. 特定の郵便番号の住所データを表示してみる

  4. 入力された郵便番号の住所データを表示する


  • おまけ:エラーメッセージを表示する①

  • おまけ:エラーメッセージを表示する②

  • おまけ:入力欄をクリックすると初期の画面に戻す

  • おわりに


(1)Nuxt.jsのプロジェクトを作成する

プロジェクトを作成したいディレクトリに移動し、以下のコマンドを実行します。

私はDesktopのpracticeというフォルダにsample-search-zipcode-appという名前のプロジェクトを作成しました。

$ cd Desktop/practice

$ npx create-nuxt-app sample-search-zipcode-app

ProjectNameなど確認する表示が出てきますが、

Choose features to install以外は初期設定のままEnterを押していって大丈夫です。

Choose features to installについてはAxiosを選択してEnterを押してください。

installが完了したら、以下のように作成したプロジェクトに移動して実行します。

$ cd sample-search-zipcode-app

$ npm run dev

localhost:3000にアクセスして、以下の画面になっていればプロジェクトの作成は完了です。

スクリーンショット 2019-04-11 15.42.52.png


(2)templateを作成する

作成したプロジェクトのpagesフォルダのindex.vueファイルを開いて、template部分を作成します。


pages/index.vue

<template>

<section class="container">
<input type="text" placeholder="郵便番号を入力"/>
<button>住所自動入力</button>
<p>都道府県:</p>
<p>住所1:</p>
<p>住所2:</p>
</section>
</template>

<script>
</script>


最終的には、郵便番号を入力して住所自動入力ボタンを押したら

郵便番号 都道府県 住所1 住所2 が自動で表示されるようにしていきます。


(3)特定の郵便番号の住所データを表示してみる

まずは、入力された郵便番号ではなく、

こちらで指定した郵便番号(今回は〒154-0024)の住所データを表示してみます。


pages/index.vue

<template>

<section class="container">
<input type="text" placeholder="郵便番号を入力"/>
<button>住所自動入力</button>
<p>{{resultData}}</p>
<p>都道府県:</p>
<p>住所1:</p>
<p>住所2:</p>
</section>
</template>

<script>
const axios = require('axios');

let url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';

export default {
async asyncData() {
let zipcode = '154-0024';
let result = await axios.get(url + zipcode);
return { resultData: result.data.results[0] };
}
}
</script>


こんな画面になっていたらOKです。

スクリーンショット

もしModule not foundのエラーが出たら、ターミナルで$npm install axiosコマンドを実行して、

再度$npm run devしてみてください。


-クロスドメイン問題

こんなエラーが出てしまったら、

スクリーンショット 2019-04-11 18.20.52.png

一旦Chromeを終了して、

$open /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dirコマンドでChromeを開いてください。

このエラーは、ほかのwebサイトからデータを取ってこようとすると制限がかかる

クロスドメイン問題が起こった場合に出ます。


-axiosとは?

axiosは、webサーバーにアクセスして必要な情報をやりとりするための機能です。

(axiosはNuxt.jsのための機能ではなく、Javascriptの一般的なライブラリです。)

const axios = require('axios');と書くと、axiosを利用できるようになります。


-asyncDataとは?

asyncDataは非同期処理をするためのNuxt.jsのメソッドです。

非同期処理とは、実行できるようになってから実行する処理のことです。今回の場合だと、

http://zipcloud.ibsnet.co.jp/api/search?zipcode=154-0024にアクセスして

住所データを取得してから、そのあとの処理を行うようにしています。

関数の前にawaitをつけることで、その関数の結果が返ってくるまで待機します。

awaitを使う場合は非同期関数を宣言するためにasyncを書いておく必要があります。


−郵便番号検索API

郵便番号検索APIは、日本郵便が提供しているデータを株式会社アイビスが加工して提供しているAPIです。

例えば、〒154-0024の住所データを取得したい場合は、

http://zipcloud.ibsnet.co.jp/api/search?zipcode=154-0024にアクセスすると

このようにデータを見ることができます。

スクリーンショット 2019-04-11 16.24.27.png

この結果を変数resultに入れておき、resultDataというプロパティ名で、

今回取得したい住所データ部分result.data.results[0]をオブジェクトとして返します。

template内では、{{プロパティ名}}でデータを表示することができます。


(4)入力された郵便番号の住所データを表示する

(3)ではasyncData内でデータ取得しましたが、asyncDataはコンポーネント生成時に自動的に実行されるため、

コンポーネントが表示された際にはすでにデータが表示されています。

これをボタンが押された時に、入力された郵便番号の住所データを表示するように、

data/methodsプロパティを使ってコードを書き換えていきます。


pages/index.vue

<template>

<section class="container">
<input type="text" placeholder="郵便番号を入力" v-model="zipcode"/>
<button @click="searchAddressInfo">住所自動入力</button>
<p>都道府県:{{addressData['address1']}}</p>
<p>住所1:{{addressData['address2']}}</p>
<p>住所2:{{addressData['address3']}}</p>
</section>
</template>

<script>
const axios = require('axios');

let url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';

export default {
data() {
return {
zipcode: '',
addressData: {}
}
},
methods: {
searchAddressInfo() {
axios.get(url + this.zipcode).then((res) => {
this.addressData = res.data.results[0];
})
}
}
}
</script>


154-0024と入力→住所自動入力ボタンを押して、このような画面になっていたらOKです。

スクリーンショット 2019-04-11 18.32.21.png

-実装の流れ

dataプロパティにzipcodeを用意して、入力された郵便番号とバインドします。

また、住所自動入力ボタンをクリックした時にsearchAddressInfoを呼び出します。

そしてdataプロパティにaddressDataを用意して、

searchAddressInfoの中でAPIから取ってきた住所データを入れます。

最後に、addressDataaddress1 address2 address3 プロパティの値を

それぞれtemplate内で表示します。

-get.then

searchAddressInfoの中では、get.thenを使ってデータを取得しています。

get.thenは以下の形で使うことができ、resの中に取得したデータが入っています。

axios.get( URL ).then((res) => { アクセス後の処理 });


おまけ:エラーメッセージを表示する①

正しい郵便番号が入力されなくてデータが取得できなかった場合に、

no dataとメッセージを表示するようにします。


pages/index.vue

<template>

<section class="container">
<p>{{message}}</p>
<input type="text" placeholder="郵便番号を入力" v-model="zipcode"/>
<button @click="searchAddressInfo">住所自動入力</button>
<p>都道府県:{{addressData['address1']}}</p>
<p>住所1:{{addressData['address2']}}</p>
<p>住所2:{{addressData['address3']}}</p>
</section>
</template>

<script>
const axios = require('axios');

let url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';

export default {
data() {
return {
zipcode: '',
addressData: {},
message: ''
}
},
methods: {
searchAddressInfo() {
axios.get(url + this.zipcode).then((res) => {
if(res.data.results == null) {
this.message = 'no data'
return;
}
this.addressData = res.data.results[0];
})
}
}
}
</script>


dataプロパティにmessageを用意して、

もしデータが取得できていなかったら(取得したデータがnullだったら)messageno dataとします。

例えば、1とかaとか間違った郵便番号を入れてno dataと表示されていたらOKです。


おまけ:エラーメッセージを表示する②

URLが間違っていたり、サーバーが停止してしまうなど、アクセスできなかった場合に

errorとメッセージを表示するようにします。

get.thenのあとに、さらにcatchメソッドを追加してエラー処理をします。


pages/index.vue

<template>

<section class="container">
<p>{{message}}</p>
<input type="text" placeholder="郵便番号を入力" v-model="zipcode"/>
<button @click="searchAddressInfo">住所自動入力</button>
<p>都道府県:{{addressData['address1']}}</p>
<p>住所1:{{addressData['address2']}}</p>
<p>住所2:{{addressData['address3']}}</p>
</section>
</template>

<script>
const axios = require('axios');

let url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';

export default {
data() {
return {
zipcode: '',
addressData: {},
message: ''
}
},
methods: {
searchAddressInfo() {
axios.get(url + this.zipcode).then((res) => {
if(res.data.results == null) {
this.message = 'no data'
return;
}
this.addressData = res.data.results[0];
}).catch((error) => {
this.message = 'error'
})
}
}
}
</script>


例えば変数urlの適当な1文字を削除して、正しい郵便番号を入力してerrorと表示されていればOKです。

おまけ:入力欄をクリックすると初期の画面に戻す

最後に、住所データが表示されている状態で入力欄をクリックした時に、初期の画面に戻すようにします。


pages/index.vue

<template>

<section class="container">
<p>{{message}}</p>
<input type="text" placeholder="郵便番号を入力" v-model="zipcode" @focus="focus"/>
<button @click="searchAddressInfo">住所自動入力</button>
<p>都道府県:{{addressData['address1']}}</p>
<p>住所1:{{addressData['address2']}}</p>
<p>住所2:{{addressData['address3']}}</p>
</section>
</template>

<script>
const axios = require('axios');

let url = 'http://zipcloud.ibsnet.co.jp/api/search?zipcode=';

export default {
data() {
return {
zipcode: '',
addressData: {},
message: ''
}
},
methods: {
searchAddressInfo() {
axios.get(url + this.zipcode).then((res) => {
if(res.data.results == null) {
this.message = 'no data'
return;
}
this.addressData = res.data.results[0];
}).catch((error) => {
this.message = 'error'
})
},
focus() {
this.zipcode = ''
this.addressData = {}
this.message = ''
}
}
}
</script>


inputに@focusを追加し、入力欄をクリックした時にfocusメソッドを呼び出し、

dataプロパティをすべて初期化します。

住所データが表示されている状態で入力欄をクリックしてみて、初期の画面に戻っていればOKです。


おわりに

引き続きNuxt.jsなどの勉強がんばりたいです。

もし間違った記載などあればご指摘いただけると幸いです。


参考

Vue.js & Nuxt.js超入門

【Nuxt.js】todoアプリを作成してみた①

【Nuxt.js】todoアプリを作成してみた②

JavaScriptの非同期処理を並列処理と勘違いしていませんか?

async/await 入門(JavaScript)

【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法

郵便番号検索API