【Vue.js】axiosを利用してAPIを使用する
- 実装したいこと
- 使用バージョン
- 実装の流れ
- そもそも、APIって?
- Tasks controller
- Routing
- CSRF対策無効化
- Vue.jsでAPIを使用する
- axiosインストール
- axios設定
- Vueファイル設定
- curl コマンド
実装したいこと
タスク管理アプリを作成しています。
APIからタスクのデータを取得して、表示させたいです。
基本的に公式の流れに沿って進めていきます。
axios を利用した API の使用 — Vue.js
また、ここまでは実装済です。
study-diary.hatenadiary.jp
使用バージョン
実装の流れ
大きな流れは、「タスク一覧を取得するAPIを生成→Vue.jsで取得」です。
Task modelは作成済です。
API作成
- Tasks controllerを作成
- routing設定
- CSRF無効化
APIの呼び出し
- axiosインストール
- Vueファイルの設定
そもそも、APIって?
API is the acronym for Application Programming Interface, which is a software intermediary that allows two applications to talk to each other. Each time you use an app like Facebook, send an instant message, or check the weather on your phone, you’re using an API.
What is an API? (Application Programming Interface) | MuleSoft
例えば、Expediaみたいな航空券予約サービスはエアラインAPIを使っていて、顧客のリクエストを受けて各社の最新の情報を提供する。
RailsでもAPIモードがあるので、APIを作成できると。
今回はこっち。恥ずかしながらRailsでAPIを生成できるのを知らなかった
Railsで超簡単API - Qiita
Tasks controller
$ bundle exec rails g controller Api::Tasks index show create update destroy --skip-routes
class Api::TasksController < ApplicationController before_action :set_task, only: %i[show update destroy] def index @tasks = Task.all render json: @tasks end def show render json: @task end def create @task = Task.new(task_params) if @task.save render json: @task else render json: @task.errors, status: :bad_request end end def update if @task.update(task_params) render json: @task else render json: @task.errors, status: :bad_request end end def destroy @task.destroy! render json: @task end private def set_task @task = Task.find(params[:id]) end def task_params params.require(:task).permit(:title) end end
Routing
Rails.application.routes.draw do root to: 'home#index' namespace :api, format: 'json' do resources :tasks end get '*path', to: 'home#index' end
namespace忘れでエラー発生
この後、curlコマンドでtaskを生成したのですが成功しませんでした。
大量のエラーメッセージが出て、VSCodeのターミナル画面ではカットされてしまったので、MacのTarminalでエラーメッセージを読むと、以下のようにrouting errorでした。
いつものように、resources :tasks
としていたのが原因でした。上記のようにname space
が必要でした。
<header> <h1>Routing Error</h1> </header> <div id="container"> <h2>No route matches [POST] "/api/tasks"</h2>
CSRF対策無効化
class ApplicationController < ActionController::Base protect_from_forgery with: :null_session # 追加 end
APIでは外部から叩かれるのでこの設定はオフにしておきます。
Vue.jsでAPIを使用する
ウェブアプリケーションを構築するとき、 API からデータを取得して表示することがよくあります。これを行うにはいくつかの方法があり、一般的なアプローチは Promise ベースの HTTP クライアントの axios を使うことです。 axios を利用した API の使用 — Vue.js
axiosインストール
$ yarn add axios
GitHub - axios/axios: Promise based HTTP client for the browser and node.js
APIから取得したデータを表示(基本構文)
axios .get('http://localhost:3000/api/tasks') .then(response => (this.tasks = response.data)) .catch(error => console.log(error)) //エラー処理。console.logでエラー表示
axios設定
import axios from 'axios' const axiosInstance = axios.create({ baseURL: 'api' }); export default axiosInstance //生成したインスタンスをexport
baseURL
will be prepended tourl
unlessurl
is absolute. It can be convenient to setbaseURL
for an instance of axios to pass relative URLs to methods of that instance. GitHub - axios/axios: Promise based HTTP client for the browser and node.js
baseURL
は不完全なurl
にurl
を補完してくれる機能。
import Vue from 'vue' import App from '../app.vue' import router from '../router' // さっき作ったaxiosインスタンスをimportする import axios from '../plugins/axios' import 'bootstrap/dist/css/bootstrap.css' Vue.config.productionTip = false // importしたaxiosをprototypeに追加する Vue.prototype.$axios = axios document.addEventListener('DOMContentLoaded', () => { const app = new Vue({ router, render: h => h(App) }).$mount() document.body.appendChild(app.$el) })
プロトタイプに追加すれば、すべてのVueインスタンスで、this.$axios.get
のように簡単に使うことができる。
Vueファイル設定
<template> <div v-for="task in tasks" :key="task.id"> //配列に入ったtasksを1つずつ表示 <span>{{ task.title }}</span> </div> </template> <script> // (先述)/packs/hello_vue.jsにprototypeを設定しているので、importしなくてOK。 // (先述)各所でthis.$axios.get~~~のようにaxiosを使うことができるようになる。 export default { name: "TaskIndex", data() { return { tasks: [] //空の配列を用意する。受け取ったデータが入る } }, created() { //インスタンス生成時にフック this.fetchTasks(); //fetchTasksメソッドを呼び出し }, methods: { fetchTasks() { this.$axios.get("tasks") //baseURLオプションを登録しているのでこのように省略して書ける .then(response => (this.tasks = response.data)) //取得したデータをtasksに代入 .catch(error => console.log(error.status)); } } } </script> <style scoped> </style>
最初自分の実装では、このファイルにimport axios from 'axios'とか全部書いていたのですが、
hello_vue.js`に設定しておくことで一々呼び出さずに済みます。
curl コマンド
ターミナル上でタスクの作成〜削除まできます。
$ curl -X POST -H "Content-Type: application/json" -d '{"title":"タスクの作成"}' localhost:3000/api/tasks
$ curl -X DELETE localhost:3000/api/tasks/(該当のID)
$ curl http://localhost:3000/api/tasks