Laravel上でVue.jsの構成をいろいろ試してみた


Laravelを使った開発をすることが多い中、ちょっと前にVue.jsを使った開発をしていて、
フロントも少し勉強し始めたandsfです。
今回はLaravel上でVue.jsを使った構成を試してみたので、記事にしました。

# 概要
Laravelには初めからVue.jsを使えるように準備されています。
インストールだったりセットアップだったりはいろいろな方が記事を書いていると思うので、
私の方ではLaravel上でVue.jsを使った簡単な実装方法を何パターンか試してみたいと思います。
処理は単なる画面遷移で、トップページとサブページをただ表示するだけですが、
それを下記２パターンで実装してみたいと思います。

# とりあえず、準備
今回は単なる画面遷移だけになるので、ページを表示するためにweb.phpを修正します。
web.phpは下記のように設定

```php5
<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
$router->get('/top', function () {
    return view('top');
});
$router->get('/sub', function () {
    return view('sub');
});
```

表示するbladeファイルは下記構成

```php5
//master.blade.php
<html>
<head>
  <meta charset="utf-8">
  @yield('assets')
</head>
<body>
  <div id="content">
    @yield('content')
  </div>
</body>
</html>
```
```php5
//top.blade.php
@extends('master')

@section('content')
<div>
  トップページ
</div>
<div>
  <a href="/sub">サブページへ</a>
</div>
@endsection
```
```php5
//sub.blade.php
@extends('master')

@section('content')
<div>
  サブページ
</div>
<div>
  <a href="/top">トップページへ</a>
</div>
@endsection
```
これでサンプルの準備は完了です。
トップページとサブページを表示する簡単な処理です。

# 試してみる
それではサンプルの処理をvue.jsを使って下記２パターンを試してみます。

## パターン１ : 既存のbladeファイルをそのままVue.jsに置き換える
Vue.jsを使った新規開発ではなかなかしないかと思います。
どちらかというと既存プロジェクトの一部改修とかになるかと思います。
このパターンを試すにあたり、このあと処理を記述するtop.jsとsub.jsをトランスパイルできるようにするためにwebpack.mix.jsを少し修正する必要があります。

```js
const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
   .js('resources/js/top.js', 'public/js')
   .js('resources/js/sub.js', 'public/js')
//   .sass('resources/sass/app.scss', 'public/css');cssは使わないので、対象から外しました
```
それではそれぞれにvue.jsを読み込むためのjsファイルとtopとsub用のcomponentファイルを準備します。

```js
// top.js
import Vue          from 'vue'
import TopComponent from './components/TopComponent'

document.addEventListener('DOMContentLoaded', () => {
  const element = document.getElementById('top');
  new Vue({
    el: element,
    render: function(render) {
      return render(TopComponent)
    }
  });
})
```
```js
// sub.js
import Vue          from 'vue'
import SubComponent from './components/SubComponent'

document.addEventListener('DOMContentLoaded', () => {
  const element = document.getElementById('sub');
  new Vue({
    el: element,
    render: (render) => {
      return render(SubComponent)
    }
  });
})
```
```js
// TopComponent
<template>
  <div>
    <div>
      サブページ
    </div>
    <div>
      <a href="/top">トップページへ</a>
    </div>
  </div>
</template>
```
```js
//SubComponent
<template>
  <div>
    <div>
      トップページ
    </div>
    <div>
      <a href="/sub">サブページへ</a>
    </div>
  </div>
</template>
```
今回のcomponentはtemplateしか記述がないので、component化する必要はなかったのですが、
処理を分離するという意味でcomponent化してみました。
それではこちらをtop.blade.phpとsub.blade.phpで読み込むように実装しましょう。

```php5
//top.blade.php
@extends('master')

@section('assets')
  <script src="{{ asset('/js/top.js') }}"></script>
@endsection

@section('content')
  <div id="top"></div>
@endsection
```
```php5
//sub.blade.php
@extends('master')

@section('assets')
  <script src="{{ asset('/js/sub.js') }}"></script>
@endsection

@section('content')
  <div id="sub"></div>
@endsection
```
これで実装は完了です。
この置き換えではサンプルで用意した処理とまったく同じ画面遷移をすることができます。
（表示している内容をただ、vue.js側によせただけです。

## パターン2 : SPA化する
こちらはvue.jsといえばって感じになるかと思います。
それでは下準備の処理をSPA化してみましょう。
まずはSPA化するにあたり必要なモジュールの追加とLaravel側の修正をします。

```
npm install vue-router
```
web.phpは下記のように修正。

```php5
//$router->get('/top', function () {
//    return view('top');
//});
//$router->get('/sub', function () {
//    return view('sub');
//});
$router->get('/{any}', function () {
    return view('index');
});
```
新規にSPA用のbladeファイル(index.blade.php)を追加します。

```php5
@extends('master')

@section('assets')
  <script src="{{ asset('/js/app.js') }}"></script>
@endsection

@section('content')
  <div id="app"></div>
@endsection
```
それではVue.js側のjsファイルとcomponentは下記のように準備します。

```js
//app.js
import Vue            from 'vue'
import VueRouter      from 'vue-router'
import IndexComponent from './components/IndexComponent.vue'
import TopComponent   from './components/TopComponent.vue'
import SubComponent   from './components/SubComponent.vue'

Vue.use(VueRouter);

const router = new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/top',
      component: TopComponent
    },
    {
      path: '/sub',
      component: SubComponent
    }
  ]
});

document.addEventListener('DOMContentLoaded', () => {
  const element = document.getElementById('app')
  new Vue({
    el: element,
    router,
    render: (render) => {
      return render(IndexComponent)
    }
  })
});
```
```js
//IndexComponent
<template>
  <div>
    <router-view />
  </div>
</template>
```
```js
//TopComponent
<template>
  <div>
    <div>
      トップページ
    </div>
    <div>
      <router-link to="/sub">サブページへ</router-link>
    </div>
  </div>
</template>
```
```js
//SubComponent
<template>
  <div>
    <div>
      サブページ
    </div>
    <div>
      <router-link to="/top">トップページへ</router-link>
    </div>
  </div>
</template>
```
これでSPA化の実装は完了です。
view-routerの使い方は[こちら](https://router.vuejs.org/ja/guide/#html)をみるとわかりやすかと思います。

# 試してみて
今回は画面遷移のみで機能要件はないですが、
Laravel上でVue.jsを使うのもとても簡単だなと思ったのが実際です！
この記事を書く上で、思ったことですがやっぱりドキュメントを読むのは重要ですね。

# 参考文献
[Readouble](https://readouble.com/)
[Vue.js](https://jp.vuejs.org/v2/guide/index.html)
[vue-router](https://router.vuejs.org/ja/guide/#html)