Vue.js初心者がaxiosを利用しAPIを叩きデータを表示させるまで

#はじめに
Vue.js は学習コストが低いと言われていますが初学者の方からしたら、
理解するのになかなか時間がかかってしまうと思います。
私も深く理解できているわけではありませんが、
これから紹介する書き方のみで
フロントのコーディングやアプリケーションを作る速さが格段にアップしたので、
この記事でVue.jsのコツを掴んでいただけたら幸いです。

# Vue CLIのダウンロード
```
$ npm install -g @vue/cli
```

# プロジェクトを作る
まずは以下のコマンドで vue のファイルを作ります。

```
$ vue create new-project
```
※この場合 new-project というディレクトリが作成されます。
<img width="741" alt="スクリーンショット 2020-02-05 11.48.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579761/14877daa-d8c8-51ab-bbde-76e7118901f5.png">
ファイルの内容をデフォルトで作るか自分でカスタマイズするか聞かれます。
今回は<strong> Router、 Vuex </strong>という機能を使うので
 `Manually select features`を選択します。
<img width="1440" alt="スクリーンショット 2020-02-05 11.50.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579761/9e6db810-867b-01ec-844f-80b8a6ef6913.png">
`spaceキー`で<strong> `Router` </strong>と<strong> `Vuex` </strong>を選択し`Enterキー` を押します。
以後も質問形式で設定を聞かれますが特にこだわりがなければ全て `Enterキー` で構いません。

```
$ cd new-project
$ npm run serve
```
`http://localhost:8080/`　このようなurlが出てきたら、
ブラウザからアクセスし以下のような画面が出れば準備完了です。
<img width="1440" alt="スクリーンショット 2020-02-05 17.09.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579761/5e0d9d84-e87e-ee30-7a51-f0821b7ff218.png">

#Hello Worldを赤色で表示
早速Vueをいじっていきます。

Vue は単一ファイルコンポーネントでコードを記述するのが基本です。
以下のような形式を単一ファイルコンポーネントと言います。

```
<template></template>
<script></script>
<style></style>
```

見てわかるように
`<template>`には HTML
`<script>`には JavaScript
`<style>`には css
を記述していきます。

Home.vueの `<template>` `<script>` `<style>` の中身を全て削除し以下のコードを書きます。
・`template`の<strong>homeクラスタグ</strong>のみ残しておいてください。
・スタイルタグは追加してください。


```
<template>
  <div class="home">
    <h1>Hello World</h1>
  </div>
</template>

<script></script>

<style scoped>
  .home{
    color: red;
  }
</style>
```

#マスタッシュ記法
ここからスクリプトタグを使っていきます。
データバインディングという操作を行います。
以下のようなコードを書きます

```
<template>
  <div class="home">
    <h1>{{hoge}}</h1>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        hoge: "ハローワールド"
      }
    }
  }
</script>
```

h1タグの中身が`ハローワールド`に変わったのが確認できたと思います。
#マスタッシュ　リスト表示方法

```
<template>
  <div class="home">
    <p>{{Vegetable.name}}</p>
    <p>{{Vegetable.price}}</p>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        Vegetable: {
          name: "にんじん",
          price: 3000000
        }
      }
    }
  }
</script>
```
`Vegetable` リストの中の `name`、`price`というように取り出します。

#v-bind　スタイル付与

h1タグを青色にします。

```
<template>
  <div class="home">
    <h1 v-bind:style="vStyle">{{hoge}}</h1>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        hoge: "ハローワールド",
        vStyle: {
          color: "blue"
        }
      }
    }
  }
</script>
```
#filter　小数点をつける
高級なにんじんの値段に小数点をつけます。

```
<template>
  <div class="home">
    <p>{{Vegetables.price | filter}}</p>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        Vegetables: {
          price: 3000000
        }
      }
    },
    filters: {
      filter(val) {
        return val.toLocaleString();
      }
    }
  }
</script>
```
数字以外に、文字にも適用できるfilterがあります。

#v-if else 表示　非表示の切り替え

```
<template>
  <div class="home">
    <p v-if="false">on</p>
    <p v-else>off</p>
  </div>
</template>
```
v-if の条件が
・true であれば on
・false であれば off
が表示されます

#v-model　inputタグと同期
input に入力した内容を pタグに表示させます。

```
<template>
  <div class="home">
    <input v-model="text" type="text">
    <p>{{text}}</p>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        text: "",
      }
    }
  }
</script>
```
inputに入力されたデータを入れるために空のデータを用意してあげます。
textデータから値、テキストを取得して描画されます。

#v-on　clickイベント

```
<template>
  <div class="home">
    <div @click="push()">click me!!</div>
  </div>
</template>

<script>
  export default{
    methods:{
      push(){
        console.log("click year！！！！")
      }
    }
  }
</script>
```
検証画面のコンソールから確認してください。
click イベント以外にもイベントはあります。

#v-for　配列でタグの複製
```
<template>
  <div class="home">
      <div v-for="data in Vegetables" :key="data.key">
      <p>{{data.name}}</p>
      <p>{{data.price}}</p>
    </div>
  </div>
</template>

<script>
  export default{
    data(){
      return{
        Vegetables:[
          {name: "じゃがいも", price: 300, key: "imo"},
          {name: "イチゴ", price: 400, key: "strawberry"},
          {name: "カボチャ", price: 500, key: "pumpkin"},
        ]
      }
    }
  }
</script>
```
`Vegetables配列`の中のデータと同じ数タグを複製しそれぞれ該当するマスタッシュ記法で書かれたタグにデータ（name、price、key）が格納されます。

イメージ図
>Vegetables配列/
　├ data/
　│　├ name/ じゃがいも
　│　├ price/ 300
　│　└ key/ imo
　├ data/
　│　├ name/ イチゴ
　│　├ price/ 400
　│　└ key/ strawberry
　└  data/
　 　├ name/ カボチャ
　 　├ price/ 500
　 　└ key/ pumpkin

#component の使い方　一例
components ディレクトリの中の HelloWorld.vue のそれぞれ
`<template>`　`<script>`　`<style>`
の中身を消して以下のコードを記述します。
※helloクラスタグのみ残してください。

###HelloWorld.vue

```
<template>
  <div class="hello">
    <h2>僕は子コンポーネント</h2>
  </div>
</template>

<script>
</script>

<style scoped>
  h2{
    font-size: 50px;
  }
</style>
```

###Home.vue
```
<template>
  <div class="home">
    <HelloWorld></HelloWorld>
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld"

  export default{
    components: {
      HelloWorld
    }
  }
</script>
```
・`import` で `components` の中の `HelloWorld.vue` を呼び出します。
※HelloWorld.vue を呼び出す際拡張子の `.vue` をつける必要はありません。
・components プロパティに登録します。
・登録したものは template タグ内で使用できるようになるのでコードを記述します。

components ディレクトリにファイルを作り上記の方法をたどると同じようにコンポーネントを作ることができます。

#props 親から子コンポーネントにデータを渡す
この記事では、Home.vue の中にある HelloWorld.vue が子コンポーネントにあたります。

###Home.vue

```
<template>
  <div class="home">
    <HelloWorld v-bind:parentText="sendChild"></HelloWorld>
  </div>
</template>

<script>
import HelloWorld from "../components/HelloWorld"

  export default{
    data(){
      return{
        sendChild: "親のコンポーネントからテキストを受けっとたよ！"
      }
    },
    components: {
      HelloWorld
    }
  }
</script>
```
・子に渡すデータに名前をつけて（parenText）親のデータ（sendChild）をバインディングします。

###HelloWorld.vue
```
<template>
  <div class="hello">
    <p>{{parentText}}</p>
  </div>
</template>

<script>
export default {
  props: ['parentText'],
}
</script>
```

props プロパティで値を受け取った物は data として扱うことができるのでマスタッシュ記法で表示します。

#Router Link(Vue Router) ページ遷移

views ディレクトリの中に RouterLink.vue ファイルを作成します。
以下のように記述します。

```
<template>
  <div class="router">
    <p>Router Link の使用ができました！！</p>
  </div>
</template>
```
Router Link を使用するために router ディレクトリの中の index.js に
RouterLink.vue を登録します。
以下のようなコードを記述します。

```
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import RouterLink from '../views/RouterLink.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/routerlink',
    name: 'routerlink',
    component: RouterLink
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
```
最後にリンクを使いたいファイルに以下のようなコードを記述していきます。
ここでは Home.vue に記述します。

```
<template>
  <div class="home">
    <router-link to="/routerlink">router-link</router-link>
  </div>
</template>
```
to でページのリンク先を指定します
router-link をクリックすることでページ遷移をすることができます。
webページのリンクの方を見てもらうと `http://localhost:8080/routerlink` 
このようにリンクの末尾が変わっていることが確認できると思います。

#ぐるなびAPI お店のデータを取得から表示
axios を用いてレストラン検索APIを叩き Vuex の store という機能を使って表示まで行います。
まずは axios のインストールから行います。
以下のコマンドを順に実行していってください。

```
$ npm install --save axios
```

```
$ npm install --save
```

次に、ぐるなびAPIを使用するために[こちらのサイト](https://api.gnavi.co.jp/api/)で会員登録をします。
登録することができたら以下のような画面に行き、
仕様書ページ、レストラン検索APIを参考にパラメータと値を入れていきます。
・左側にパラメータ（例 keyid）
・右側に値

<img width="1440" alt="スクリーンショット 2020-02-05 23.53.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579761/caca5232-ea0a-a839-1a9f-1873b4cc36f2.png">

この記事では、
・表示件数
・wifiの有無
を条件に絞ります。

<img width="1440" alt="スクリーンショット 2020-02-06 1.03.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579761/57d3cc93-92a3-57d5-cab4-d9c83b96e401.png">

入力ができたら`クエリを送信`ボタンを押し URL を、コピーします。
store ディレクトリの中の index.js ファイルに、以下のようなコードを入力し
コピーした URL を`ここに挿入`とういう部分にペーストしてください。

###store / index.js
```
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    dataSet: []
  },
  mutations: {
    mutateDataSet(state, payload) {
      state.dataSet = payload
    }
  },
  actions: {
    commitDataSet(store) {
      return axios.get("ここに挿入")
        .then(response => {
          store.commit('mutateDataSet', response.data.rest)
        })
        .catch((reason) => {
          console.log(reason.message)
        })
    }
  }
}) 
```
importでaxiosを使えるようにします。
表示させたいページ（RouterLink.vue）に以下のコードを記述します。

###RouterLink.vue
```
<template>
  <div class="about">
    <ul v-for="(value, index) in shopName" :key="index">
      <li>{{value}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      shopName: ""
    };
  },
  created() {
    this.$store.dispatch('commitDataSet')
  },
  mounted() {
    var list = [];
    this.$store.state.dataSet.forEach(function(value) {
      list.push(value.name);
    });
    this.shopName = list;
  }
};
</script>
```
・created 内で store にアクセスして dispatch メソッドで action 内の関数を実行します。
・store の action メソッドが実行され値が取得されます。
・commit で mutations にアクセスし、データを入れます。
・mutations から state にアクセスし dataSetにデータが入ります。
・mounted で state 内のデータにアクセスし、forEach メソッドでデータが一個ずつ配列として list に入ります。
・list を shopName に代入することで RouterLink.vue 内で data として扱うことができるようになります。
・配列 shopName を v-for で表示させれば実装完了です。

いろいろ条件を変えて遊んでみてください。

###イメージ
>RouterLink.vue　　　　　　store / index.js
　└ created     ーー＞　action（commitDataSet）実行
　 　　　　　　　　　　　　　　↓
　 　　　　　　　　　　　　  mutation
　 　　　　　　　　　　　　　　↓
　  　mounted　　　　 ＜ーー　state
　 　　 ↓
　　　描画