RailsAPIからタスク一覧取得/ 初めてのVue.js④

前回の続き　→ https://qiita.com/mmaumtjgj/items/7dd150e44a20c7922319

先に事前準備としてAPIの作成を行う。
①``% rails g model Task title:string`` ←t.string :title, null: falseにする。

②``% rails g controller Api::Tasks index show create update destroy --skip-routes``にてコマンドを打ち、フォルダ構成にあったルーティングを記述する。

③``controllers/api/tasks_controller.rb``を作成し``json``で中身を記入。中身は割愛。

④``application_controller.rb`` に ``protect_from_forgery with: :null_session``を追記。

これはCSRF（クロスサイトリクエストフォージェリ：　リクエスト時に正統なトークンも一緒に送らないとサーバ側で当該リクエストを不正なものとみなし弾く機能）という脆弱性に対する機能を切るコード。

今回はアクセストークンの設定をしていないので、これを記載しないとPOSTが出来ない。

## axiosのインストール
``axios``とは、GETやPOSTのようなHTTPリクエストを使ってサーバからデータの取得やデータへのデータ送信を行うことができるというもの。まずはこれをインストールする。

```
% yarn add axios
```
## ``axios``の基本的な使い方
```vue
<script>
import axios from 'axios'

export default {
  data(){
    return{
      変数名: 初期値
    }
  },
  mounted(){
    axios
      .get('URL')
      .then(res => (this.変数名 = res))
  }
}
</script>
```

``mounted``の中で``axios``の処理を行う。

``mounted``はビューインスタンスを生成するタイミングで実行する処理を記述する。
簡単に言うと、ブラウザからぺージにアクセスがあった際に、実行させたい処理のこと。

こういった特定の状態になったタイミングで自動的に呼び出される関数を[ライフサイクルフック](https://jp.vuejs.org/v2/guide/instance.html#%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB%E3%83%80%E3%82%A4%E3%82%A2%E3%82%B0%E3%83%A9%E3%83%A0)という。

最もよく使われるのは``created``だが、その他各処理が実行されるタイミング等は公式にある図解が分かりやすい。

#### mounted の中の axios
mountedの中のaxiosで、importしたaxiosを使っている。
``この処理がAPIからデータを取得する処理``になる。

```vuejs
<script>
//省略
mounted(){
    axios
      .get('URL')
      .then(res => (this.変数名 = res))
  }
}
</script>

//上記は↓基本的にこのようになっている
axios
  .HTTPメソッド('HTTPアクセスするパス')
  .then( (変数名) => { 処理 })
```
変数名でよく使われるのは、``response``や省略形の``res``が多い。

``then``は通信に成功した場合に実行される処理。
取得してきたデータは指定した変数に格納される。（上記の``then``はアロー関数で記述しているが、``function``を使っても書ける。）

| メソッド | 内容 |
|:-:|:-:|
|  then |  通信に成功したときに行う処理 |
|  catch | 通信に失敗したときに行う処理（エラー発生時）  |
|  finaly |  通信の成功/失敗に関わらず必ず実行する処理 |

---

HTTPメソッドに関しては、データの取得であれば``get``を覚えておけば基本的には問題ない。

| HTTPメソッド | 内容 | 使い方 |
|:-:|:-:|:-:|
| request  | URLやメソッドを指定	  |  axios.request(config) |
| get  | GETメソッドでアクセス。データを取得	  |  axios.get(url[, config]) |
|  delete | DELETEメソッドでアクセス。データを削除|   axios.delete(url[, config])|
|   head|  HEADメソッドでアクセス。ヘッダ情報だけを取得 |  axios.head(url[, config]) |
|  options | OPTIONSメソッドでアクセス。許容しているHTTPメソッドを取得	  |  axios.options(url[, config]) |
|  post |POSTメソッドでアクセス。新規追加	   |  axios.post(url[, data[, config]]) |
|  put |  PUTメソッドでアクセス。データ全体を更新	 |  axios.put(url[, data[, config]]) |
|  patch |PUTメソッドでアクセス。データの一部を更新   |axios.patch(url[, data[, config]])   |

``axios.get(url[, config])``の引数のにある、``[, config]``は省略可能という意味。``config``では``axios``で接続するときの追加情報を記述することができる。

**``requestメソッド``と``getメソッド``の比較**
下記にある、requestメソッドは次のgetメソッドと同じ処理になる。

```js
axios.request{
  method: 'メソッド名',
  url: 'URL',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
}

//↓getメソッドで書き変え

axios.get('URL', {
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});
```

``axios``の``getメソッド``で取得できるデータは、データの種類ごとにプロパティが分かれている。

| プロパティ | 内容 |
|:-:|:-:|
|  data | サーバーから提供されたデータ  |
| status  |  サーバーから返されたステータスコード |
| statusText  | サーバーから返されたステータスメッセージ  |
| haeders  |サーバーから返されたヘッダ情報（Response Headers）   |
| config  |  axiosがリクエストに使った情報 |
| request  | レスポンスによって生成されたリクエスト  |

## axiosの設定
インストールが出来たら、``plugins/axios.js``ファイルを作成する。

上記の``axios``の使い方で、``.get('URL')``という表記がある。
今回はタスク一覧機能を入れるだけだが、本来はGETだけでなく、POSTやDELETEなども使う場面がある。

各コンポーネントでインポート処理を書くのは面倒なので、インスタンス化を行う。

またURLについて、普通に書けば``axios.get('https://localhost:3000/api/tasks')``となるが、本番環境では動かなくなってしまうので、``baseURLオプション``を行う。

``baseURLオプション``とは``axios``に指定するURLからドメイン名（またはドメイン名以降も）を省略することができる。

つまり``plugins/axios.js``ファイルは、環境にかかわらず、ルーティングで示した中身を取ってくれるようにしている。

```plugins/axios.js
import axios from 'axios'

const axiosInstance = axios.create({
    baseURL: 'api'
})

export default axiosInstance
```

``hello.vue.js``にこの``axios.js``を使えるようインポートする。
```app/javascript/packs/hello_vue.js
import Vue from 'vue'
  import App from '../app.vue'
  import 'bootstrap/dist/css/bootstrap.css'
  import router from '../router'
  import axios from '../plugins/axios.js' //ここを追加

Vue.config.productionTip = false
Vue.prototype.$axios = axios  //ここを追加
//Vue.prototypeにプロパティやメソッドを追加することで、全てのVueインスタンスで利用可能にする

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    router,
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)
})
```

## タスク一覧取得（GET）
```javascript/pages/task/index.vue
<template>
    <div id="app" class="d-flex flex-column min-vh-100">
        <div class="d-flex">
            <div class="col-4 bg-light rounded shadow m-3 p-3">
                <div class="h4">TODO</div>
                <div v-for="task in tasks" :key="task.id" class="bg-white border shadow-sm rounded my-2 p-4">
                    <span>{{ task.title }}</span>
                </div>
            </div>
        </div>
        <div class="text-center">
            <router-link to="/"><button class="btn btn-dark mt-5 router-link-active">戻る</button></router-link>
        </div>
    </div>
</template>

<script>
export default {
  name: "TaskIndex",
  data() {
    return {
      tasks: [] // 空の配列を用意し、受け取ったデータを入れる
    }
  },
  created() { //インスタンス作成時に実行される
    this.fetchTasks(); // 下で定義されたfetchTasksメソッドを実行
    },
    methods: {
        fetchTasks() {
        this.$axios.get("tasks") // baseURLオプション
        .then(res => this.tasks = res.data) // 取得したデータをtasksに代入
        .catch(err => console.log(err.status)); //エラー処理 console.logでエラー表示
        }
    }
}
</script>
```

## 参考記事
[axiosとは何か？Vue.jsでAPIのデータを取得する方法｜取得したデータの中身や処理の指定方法（変数名の変更, then, catch, finally）](https://prograshi.com/language/vue-js/axios/)
[【Rails】RailsでDBからデータを読み込み、Vue.jsを通じてブラウザに出力する方法](https://qiita.com/terufumi1122/items/98bd4d1835fabfb700af)