8
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel チュートリアルのレイアウトをVue.jsで置き換える

Posted at

Laravel + Vue.js開発の勉強として
Laravelチュートリアル(基本のタスクリスト)のレイアウトをVue.jsで置き換えてみた作業記録

構成

  • Laravel:APIサーバー(DBのCRUD処理を提供)
  • Vue.js:フロントエンド処理一式

元ネタ

バージョン

  • Laravel 5.7
  • Vue.js 2.5.17

完成品

Laravel API作成

API仕様

Method URI Action Description
POST api/task App\Http\Controllers\TaskController@store 新規タスク作成
DELETE api/task{id} App\Http\Controllers\TaskController@destroy タスク削除
GET api/tasks App\Http\Controllers\TaskController@index タスク一覧取得

Taskテーブルの設定

terminal
php artisan make:migration create_tasks_table --create=tasks
database\migrations\xxxx_create_tasks_table.php
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }

マイグレーション実行

terminal
php artisan migrate

Taskモデルを作成

terminal
php artisan make:model Task

ルーティング

routes\api.php
/**
 * Display All Tasks
 */
Route::get('tasks', 'TaskController@index');

/**
 * Add A New Task
 */
Route::post('task', 'TaskController@store');

/**
 * Delete An Existing Task
 */
Route::delete('task/{id}', 'TaskController@destroy');

Taskコントローラー作成

terminal
php artisan make:controller TaskController --resource
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Task;
use App\Http\Resources\TaskResource;

class TaskController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $tasks = Task::orderBy('created_at', 'asc')->get();

        return TaskResource::collection($tasks);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $task = new Task;

        $task->name = $request->name;

        if($task->save()) {
            return new TaskResource($task);
        }
    } 

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $task = Task::findOrFail($id);

        if ($task->delete()) {
            return new TaskResource($task);
        }
    }
}

リソース作成

terminal
php artisan make:resource TaskResource

レスポンスを送り返す時に、JSONへ変換する必要のある属性の配列を返す、
toArrayメソッドをリソースクラスで定義する。

app\Http\Resources\TaskResource.php
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
        ];
    }

Taskリストページ作成

ルーティング

routes\web.php
Route::get('/', function () {
    return view('tasks');
});

View

ポイントを抜粋して解説、
ファイル全体は以下を参照
https://github.com/thanatos27/laravel-vue-quickstart/blob/master/resources/views/tasks.blade.php

CSRF保護

resources\views\tasks.blade.php
        <!-- CSRF Protection -->
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <script>window.Laravel = { csrfToken: '{{ csrf_token() }}' }</script>

Vueカスタム要素呼び出し部分

<navbar></navbar>:ナビゲーションバー
<tasks></tasks>:タスクリスト

resources\views\tasks.blade.php
        <div id="app">
            <navbar></navbar>
            <div class="container">
                <tasks></tasks>
            </div>
        </div>

フロントエンド(Vue.js)

quickstart-basicのテンプレートファイルをベースにVue.jsでリプレース
https://github.com/laravel/quickstart-basic/blob/master/resources/views/tasks.blade.php

コンポーネント登録

resources\js\app.js
Vue.component('navbar', require('./components/Navbar.vue'));
Vue.component('questionnaires', require('./components/Tasks.vue'));

ナビゲーションバー

resources\js\components\Navbar.vue
<template>
    <nav class="navbar navbar-default">
        <div class="container">
            <div class="navbar-header">

                <!-- Branding Image -->
                <a class="navbar-brand" href="/">
                    Task List
                </a>
            </div>
        </div>
    </nav>
</template>

タスクリスト

ポイントを抜粋して解説、
ファイル全体は以下を参照
https://github.com/thanatos27/laravel-vue-quickstart/blob/master/resources/js/components/Tasks.vue

表示/非表示

Laravelの@ifをVueのv-show構文で置き換え

resources/js/components/Tasks.vue
<!-- Current Tasks -->
<div v-show="tasks.length">
    <div class="panel panel-default">
        <div class="panel-heading">
            Current Tasks
        </div>

繰り返し制御

Laravelの@foreachをVueのv-for構文で置き換え

resources/js/components/Tasks.vue
<tr v-for="task in tasks" v-bind:key="task.id">
    <td class="table-text"><div>{{ task.name }}</div></td>

    <!-- Task Delete Button -->
    <td>
        <button @click="deleteTask(task.id)" class="btn btn-danger">
            <i class="fa fa-btn fa-trash"></i>Delete
        </button>
    </td>
</tr>

ボタンアクション

@clickで対応するmethodsを呼び出す

resources/js/components/Tasks.vue
<!-- Add Task Button -->
<div class="form-group">
  <div class="col-sm-offset-3 col-sm-6">
        <button @click="addTask()" class="btn btn-default">
            <i class="fa fa-btn fa-plus"></i>Add Task
        </button>
    </div>
</div>

methods

fetchAPIで各種Laravel APIにリクエストをする

fetchTasks

タスク一覧取得
URI:api/tasks
Method:GET

resources/js/components/Tasks.vue
fetchTasks() {
    fetch('api/tasks')
    .then(res => res.json())
    .then(res => {
        this.tasks = res.data;
    })
    .catch(err => console.log(err))
},

addTask

新規タスク追加
URI:api/task
Method:POST

resources/js/components/Tasks.vue
addTask() {
    this.errors = [];
    if(!this.task.name) {
        this.errors.push('Name required.');
        return;
    }

    fetch('api/task', {
        method: 'post',
        body: JSON.stringify(this.task),
        headers: {
            'content-type': 'application/json'
        }
    })
    .then(res => res.json())
    .then(data => {
        this.task.name = '';
        this.fetchTasks();
    })
    .catch(err => console.log(err))
},

deleteTask

タスク削除
URI:api/task/{id}
Method:`DELETE

resources/js/components/Tasks.vue
deleteTask(id) {
    fetch(`api/task/${id}`, {
        method: 'delete'
    })
    .then(res => res.json())
    .then(data => {
        this.fetchTasks();
    })
    .catch(err => console.log(err))
}

簡易的バリデーション処理

resources/js/components/Tasks.vue
addTask() {
    this.errors = [];
    if(!this.task.name) {
        this.errors.push('Name required.');
        return;
    }
resources/js/components/Tasks.vue
<!-- Display Validation Errors -->
<div v-show="errors.length" class="alert alert-danger">
    <strong>Whoops! Something went wrong!</strong>
    <br><br>

    <ul>
        <li v-for="error in errors" v-bind:key="error">{{ error }}</li>
    </ul>
</div>

以上

8
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?