見出し画像

Laravel + Vue.js ユーザー一覧を作成してみる(フロント編)

前回user APIを作成したので、Vue.jsを使ってフロント部分を作っていきたいと思います〜🙌

Vue CLIを使う

いつもはNuxtばっかなんですが、今回はVue CLIで作ってみたいと思います💡

ここで躓いたのは、$ vue create my-project したときに、defaultを選んじゃだめってこと(!)Manually selectって難しそうじゃん・・と思ってdefault選択したら、自分でrouterやvuex導入するの難しかった。

スクリーンショット 2020-01-04 0.07.11

だいたいrouterとか必要だと思うので、manuallyにしましょう。今回はこんな感じで設定!

スクリーンショット 2020-01-04 0.11.22

Userページの作成

早速、表示させるページをsrc/views/User.vue作成していく!

<template>
 <div class="user">
   <h1>The Prime Minister of Japan</h1>
   <table class="user-table">
     <tr>
       <th>名前</th>
       <th>写真</th>
     </tr>
     <tr>
       <td >ここに名前を入れる</td>
       <td>ここに写真を入れる</td>
     </tr>
   </table>
 </div>
</template>

とりあえずこんな感じ??🐥

Routerの設定

次にルーティングを設定。Vue CLIでRouterを選択しているとsrc/router/index.tsファイルが既に用意されているので修正するだけ。

import User from '../views/User.vue'

const routes = [
 {
   path: '/user',
   name: 'user',
   component: User
 }
]

Vuexの設定

VuexもVue CLI作成時に選択しているとデフォルトのsrc/store/index.tsファイルが用意されています。

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'

Vue.use(Vuex)
export default new Vuex.Store({
 modules: {
   user
 }
})

ストアはmodulesにまとめたいので、modulesディレクトリを作成してuser.tsを作ります。こんなかんじ。TypeScript全くわからんなのでとりあえずany書いておきます。ここは今後修正していく😥

import Vue from 'vue'
const axios = require('axios');

const state = {
   users: null
}
const getters = {}
const actions = {
   getUsers({ commit }:any) {
       axios.get('http://127.0.0.1:10080/api/user').then((res: any) => {
           commit('setUsers', res.data);
       })
   }
}
const mutations = {
   setUsers(state:any , payload: any) {
       Vue.set(state, 'users', payload)
   }
}
export default {
   namespaced: true,
   state,
   getters,
   actions,
   mutations
}

ここで見てほしいのは、getUsersアクションでaxiosを使って前回Laravelで作ったuser APIを取得していることです。(後述しますが、この書き方だとCORSに引っかかってしまうのでうまくいきません・・😣)

次に、先ほど作成したUserコンポーネントにデータを取得する処理を追加します。

<script>
import { mapState } from 'vuex'

export default {
 mounted() {
   this.$store.dispatch('user/getUsers')
 },
 computed: {
   ...mapState('user', ['users'])
 }
}
</script>

mounted時にuserストアをdispatchし、データを取得しています。mapStateで定義しているusersをtemplate内のtableタグ中で書いてあげれば表示されるはず・・!

      <tr v-for="(user, i) in users.users" :key="i">
       <td class="user-name">{{ user.name }}</td>
       <td><img class="user-image" :src="user.icon_url"></td>
     </tr>

CORSエラー

やっぱりクロスドメインによるエラーが出た😫

今回はLaravelとVueのリポジトリを分けており、Laravel→http://127.0.0.1:10080/ 、Vue→http://localhost:8888 で開発していたからですね・・。

Access to XMLHttpRequest at 'http://127.0.0.1:10080/api/user' from origin 'http://localhost:8888' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:8888/' that is not equal to the supplied origin.

スクリーンショット 2020-01-04 0.32.54

LaravelのCORS設定

こちらのQiitaを参考にさせていただきました・・!🙏

CORS用のミドルウェアを作成します。

$ php artisan make:middleware Cors

ミドルウェアの中にheaderの設定を追加します。

    public function handle($request, Closure $next)
   {
       $url = env('APP_URL');
       return $next($request)
           ->header('Access-Control-Allow-Origin', $url)
           ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
           ->header('Access-Control-Allow-Headers', 'Content-Type');
   }

そして、src/routes/api.phpでmiddlewareを使うよう設定📝

Route::middleware(['cors'])->group( function() {
   Route::options('user', function () {
       return response()->json();
   });
   Route::get('/user', "API\UserController@index");
})

これでOKかな?設定する前のHeaderはこんな感じだったのが・・

画像4

設定後Access-Controlが設定されています!ヤッター

画像5

Vue.jsのCORS設定

次に、フロント部分のCORSも設定していきます。

まずaxios.getしているsrc/store/modules/user.tsファイルを修正

    getUsers({ commit }:any) {
       // 修正前 axios.get('http://127.0.0.1:10080/api/user')
       axios.get('/api/user').then((res: any) => {
           commit('setUsers', res.data);
       })
   }

/api/userしか記述していないのにデータが取得できる理由は、vue.config.jsにproxy設定を記述しているからです。このtarget部分ですね!

// vue.config.js
module.exports = {
   // options...
   devServer: {
       public: 'localhost',
       port: 8888,
       disableHostCheck: true,
       proxy: {
           'api/': {
               target: 'http://127.0.0.1:10080'
           }
       }
   }
}

これで無事にデータが取得でき、表示成功🤗やったね!

スクリーンショット 2020-01-03 22.06.41

Larabel入門を参考にしています。


スキ頂けると嬉しいです〜