Vue.js+BootstrapでAPIを叩いてその結果をCardで表示する

#はじめに
かれこれ3日ぐらい詰まってた問題が解決したので軽くまとめておこうと思います。データベースを検索するAPIを使ってその結果をCardで表示する感じです。

#完成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861182/20afdc1f-2d77-e669-5df5-3e81b165b7ec.png)

#つかうもの
・Vue.js
・Bootstrap
・axios

#やってみよう
まずは検索フォーム自体の設計です。これは横一列にするのに苦戦しただけでサクッとできました。

```song.vue
  <div>
    <div class="container">
      <form class="form-inline mx-auto" style="width: 500px;">
        <div class="form-group">
        <select class="form-control" v-model="type">
          <option>曲名から</option>
          <option>アーティスト名から(未実装)</option>
        </select>
        <input class="form-control" type="search" placeholder="Search" aria-label="Search" v-model="keyword">
        <button class="btn btn-outline-success" type="submit" v-on:click="Search()">Search</button>
        </div>
      </form>
      <div><br>検索は完全一致です<br></div>
    </div>
  </div>
```

将来的な事を考えてSelectという項目も用意しておりますが今は意味ないです。v-modelで変数を指定して、v-on:clickで検索プログラム自体を呼び出しましょう。

次はそれを表示する部分です。

```song.vue
    <div>
        <div class="container">
          <div class="row">
          <div class="card border-info col-sm-4" v-for="item in items" :key="item.Artist">
            <div class="card-body">
              <h2 class="card-title">{{ item.Title }}</h2>
              <ul class="list-group list-group-flush">
                <li class="list-group-item">アーティスト名：{{ item.Artist }}</li>
                <li class="list-group-item">作詞：{{ item.Word }}</li>
                <li class="list-group-item">作曲：{{ item.Composer }}</li>
                <li class="list-group-item">編曲：{{ item.Arranger }}</li>
                <li class="list-group-item">作品：{{ item.TieUp}}</li>
                <li class="list-group-item">ブランド：{{ item.Brand }}</li>
                <li class="list-group-item">ジャンル： {{ item.Genre }}</li>
              </ul>
              <button class="btn btn-outline-info">編集</button>
            </div>
          </div>
          </div>
        </div>
    </div>
```

編集ボタンはただの飾りです。今回の条件ではキー設定は特に使わない気もしますがいれないとエラーになるのでいれておきます。
これでitemsというマップが入った配列を1つ1つCardにしていきその中の項目にアクセスできるようになります。

そして肝心というかかなり苦戦したScript部分です。

```vuejs:song.vue
<script>
import axios from "axios";

export default {
  name: "song",
  data: function () {
    return{
      type: "曲名から",
      keyword: "",
      items: []
    }
  },
  methods: {
    Search: async function (){
      this.items = await search2.get(this.type, this.keyword)
      console.log(this.items)
    }
  }
}

let search2 = {
  get: async function (type, keyword){
    const res = await axios.get(' APIのURL ?title='+keyword)
    console.log(res.data.Items)
    return res.data.Items
  }
}
</script>
```

ポイントは非同期処理が入っているところです。欲しいのはPromise型ではなく普通の配列なのでSearchメソッド自体もasyncにしてawaitを使う事によりPromise型を普通の配列にしちゃいます。僕は単純な変数の打ち間違いとこれで3日を無駄にしました。
あとデバッグ用にコンソロールにいろいろ表示してますがこれはお好みでどうぞ。

#コンポーネント全景
```vuejs:song.vue
<template>
  <div>
  <div class="jumbotron-fluid">
    <div class="container">
      <h1 class="display-3">楽曲の検索</h1>
      <p class="lead">Search for song</p>
    </div>
  </div>
    <br>
    <br>
  <div>
    <div class="container">
      <form class="form-inline mx-auto" style="width: 500px;">
        <div class="form-group">
        <select class="form-control" v-model="type">
          <option>曲名から</option>
          <option>アーティスト名から(未実装)</option>
        </select>
        <input class="form-control" type="search" placeholder="Search" aria-label="Search" v-model="keyword">
        <button class="btn btn-outline-success" type="submit" v-on:click="Search()">Search</button>
        </div>
      </form>
      <div><br>検索は完全一致です<br></div>
    </div>
  </div>
    <div><hr></div>
    <div>
        <div class="container">
          <div class="row">
          <div class="card border-info col-sm-4" v-for="item in items" :key="item.Artist">
            <div class="card-body">
              <h2 class="card-title">{{ item.Title }}</h2>
              <ul class="list-group list-group-flush">
                <li class="list-group-item">アーティスト名：{{ item.Artist }}</li>
                <li class="list-group-item">作詞：{{ item.Word }}</li>
                <li class="list-group-item">作曲：{{ item.Composer }}</li>
                <li class="list-group-item">編曲：{{ item.Arranger }}</li>
                <li class="list-group-item">作品：{{ item.TieUp}}</li>
                <li class="list-group-item">ブランド：{{ item.Brand }}</li>
                <li class="list-group-item">ジャンル： {{ item.Genre }}</li>
              </ul>
              <button class="btn btn-outline-info">編集</button>
            </div>
          </div>
          </div>
        </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "song",
  data: function () {
    return{
      type: "曲名から",
      keyword: "",
      items: [],
      list: []
    }
  },
  methods: {
    Search: async function (){
      this.items = await search2.get(this.type, this.keyword)
      console.log(this.items)
    }
  }
}

let search2 = {
  get: async function (type, keyword){
    const res = await axios.get(' APIのURL ?title='+keyword)
    console.log(res.data.Items)
    return res.data.Items
  }
}
</script>

<style scoped>

</style>
```

#最後に
分かっちゃえば簡単な事でも意外とがっつり躓くことってありますよ。今回はどうしても分からなかったので他人の力を借りようとteratailを使いました。回答してくれた方にこの場を借りてお礼もうしあげます。
https://teratail.com/questions/304455