Vue.jsでぐるなびAPIからデータを取得する


環境

macOS Catalina 10.15.3
vue 3.0.1

vue-cliでプロジェクトを作成

ターミナルで以下のコマンドを叩く

$ vue crate my-project

presetはBabel,Router,Vuex,Linter/Formatter,Unit Testingを選択しています

作成できたら、一度動作確認

$ cd my-project
$ npm run serve

これでlocalhost:8080に接続
以下の画面が表示されるはずです

ぐるなびAPIのアクセスキーを取得

ぐるなびAPIを使用するにはアクセスキーが必要になるので、以下のサイトから取得してください
ぐるなび Web Service

ぐるなびAPIからデータを取得

まず/srcの直下にapiというディレクトリを作成します。
この中にgnavi.jsというファイルを作成し、この中にぐるなびAPIからデータを取得する関数を定義します。

my-project
 └── src/
     └── api/
         └── gnavi.js

単一ファイルに直接メソッドを定義することもできますが、分けた方が保守性が高くなることやコードの重複を減らすことができます。

データの取得には、axiosを使用して取得するため、インストールしていない方は以下のコマンドを叩いてください。

$ npm install --save axios

では、ぐるなびAPIからデータを取得していきます。

gnavi.js
import axios from 'axios'

export default {
  searchShops(shopName) {
    // Promiseを返す
    return new Promise((resolve, reject) => {
      axios
        .get("https://api.gnavi.co.jp/RestSearchAPI/v3/?keyid=<ぐるなびAPIから取得したアクセスキー>", {
          // 店名検索
          params: {
            name: shopName
          })
          // 検索結果をresolve
          .then(shops => {
            resolve(shops.data.rest);
          })
          // エラーハンドリング
          catch(error => {
            const errorStatus = error.response.status;

            switch (errorStatus) {
              case 400:
                reject("不正なパラメータが指定されました");
                break;

              case 401:
                reject("不正なアクセスです");
                break;

              case 404:
                reject("お店が見つかりませんでした");
                break;

              case 405:
                reject("不正なアクセスです");
                break;

              case 429:
                reject("リクエスト回数上限超過");
                break;

              case 500:
                reject("処理中にエラーが発生しました");
                break;

              default:
                reject("不明なエラーです");
                break;
            }
        });
    })
  }
}

これでぐるなびAPIからデータを取得することができます。
これから、このデータを表示するためにsrc/components/HelloWorld.vueを書き直します。

HelloWorld.vue
<template>
  <v-container>
    <v-row>
      <v-col cols="12" xs="10" sm="8" md="6" lg="4">
        <v-text-field label="店名" v-model="shopName" />
      </v-col>
      <v-col cols="2">
        <v-btn @click="loadShops" :loading="loading">検索</v-btn>
      </v-col>
    </v-row>

    <v-alert v-if="error_msg" type="error">{{ error_msg }}</v-alert>

    <v-row v-if="shops">
      <v-col cols="12" xs="12" sm="6" md="4" lg="3" v-for="(shop, index) in shops" :key="index">
        <v-card>
          <v-img :src="shop.image_url.shop_image1" />
          <v-card-title>{{ shop.name }}</v-card-title>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import gnavi from "@/api/gnavi.js";

export default {
  name: "HelloWorld",

  data() {
    return {
      shopName: null,
      shops: null,
      error_msg: null,
      loading: false
    };
  },

  methods: {
    loadShops() {
      this.shops = null;
      this.error_msg = null;
      this.loading = true;

      gnavi
        .searchShops(this.shopName)
        .then(res => {
          this.shops = res;
        })
        .catch(err => {
          this.error_msg = err;
        })
        .finally(() => {
          this.loading = false;
        });
    }
  }
};
</script>

デザインを簡単に整えるためにvuetifyを使用しています。
特に今回の内容とは、関係ないので導入などは省略します。

実行すると、こんな感じになります。

最初の画面

やまやと入力して検索ボタンを押すと

検索結果が0件の場合

まとめ

今回は、ぐるなびAPIからデータを取得しました。
Vue.jsやPromiseなどの説明を省いたので、Vue.jsやJavaScriptに触れたことがない方は、わからないところがあったかもしれません。
ただ、今回のコードをコピペすれば、とりあえず動くと思うので(vuetifyをインストールすれば)、いろいろ試して見てください!