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


はじめに

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

Vue CLIのダウンロード

$ npm install -g @vue/cli

プロジェクトを作る

まずは以下のコマンドで vue のファイルを作ります。

$ vue create new-project

※この場合 new-project というディレクトリが作成されます。

ファイルの内容をデフォルトで作るか自分でカスタマイズするか聞かれます。
今回は Router、 Vuex という機能を使うので
Manually select featuresを選択します。

spaceキー Router Vuex を選択しEnterキー を押します。
以後も質問形式で設定を聞かれますが特にこだわりがなければ全て Enterキー で構いません。

$ cd new-project
$ npm run serve

http://localhost:8080/ このようなurlが出てきたら、
ブラウザからアクセスし以下のような画面が出れば準備完了です。

Hello Worldを赤色で表示

早速Vueをいじっていきます。

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

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

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

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

<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 リストの中の namepriceというように取り出します。

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>

importcomponents の中の 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を使用するためにこちらのサイトで会員登録をします。
登録することができたら以下のような画面に行き、
仕様書ページ、レストラン検索APIを参考にパラメータと値を入れていきます。
・左側にパラメータ(例 keyid)
・右側に値

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

入力ができたらクエリを送信ボタンを押し 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
     ↓
   描画