LaravelからVueを使ってSPAっぽくする

自分の書いた[Laravel 5.4 + Vue 2.1 でSPAアプリケーション作成チュートリアル](http://qiita.com/acro5piano/items/f33381fc60408abe9865)が長すぎるので要点をまとめた。

# ディレクトリ構成 

関係ある部分だけ。
JSが深い、なんとかならないか。

```
.
|-- app
|   `-- Models
|       `-- Article.php
|-- package.json
|-- resources
|   |-- views
|   |   `-- app.blade.php
|   `-- assets
|       `-- js
|           |-- app.js
|           |-- bootstrap.js
|           `-- components
|               |-- Articles
|               |   `-- Index.vue
|               `-- Layouts
|                   `-- Navbar.vue
|-- routes
    |-- api.php
    `-- web.php
```


# サーバーサイド Routing

```php:routes/web.php
<?php

Route::get('/{any}', function () {
    return view('app');
})->where('any', '.*');
```

```php:routes/api.php
Route::group(['middleware' => 'api'], function() {
    Route::get('articles',  function() {
        $articles = Article::all()->take(5);
        return $articles;
    });
});
```

`GET /api/articles` というルーティングが定義される
上記以外は全て、SPAのエントリーポイント `app.blade.php` が返される

# View

SPAのエントリーポイントである

```php:resouces/views/app.blade.php
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}">
    <head>
        <script>
            window.Laravel = {};
            window.Laravel.csrfToken = "{{ csrf_token() }}";
        </script>
    </head>
    <body>
        <div id="app">
            <navbar></navbar>
            <div class="container">
                <router-view></router-view>
            </div>
        </div>
    </body>
    <script src="{{ mix('js/app.js') }}"></script>
</html>
```

`<router-view></router-view>` が `vue-router` によって動的に変わる

# JS

### app.js

クライアントサイドのルーティングとComponentを定義する。

```js:resources/assets/js/app.js
import Vue from 'vue'
import VueRouter from 'vue-router'

require('./bootstrap')

Vue.use(VueRouter)

Vue.component('navbar', require('./components/Layouts/Navbar.vue'))

const router = new VueRouter({
    mode: 'history',
    routes: [
        { path: '/', 
          component: require('./components/Articles/Index.vue') 
        }
    ]
})

const app = new Vue({
    router
}).$mount('#app')
```

### bootstrap.js

マニフェスト的なファイル

```js:resources/assets/js/bootstrap.js
// ...

window.axios = require('axios')

window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': window.Laravel.csrfToken,
    'X-Requested-With': 'XMLHttpRequest'
}

Vue.prototype.$http = axios

// ...
```

# Vue Component

MVCのVに当たる部分。

```html:resources/assets/js/components/Layouts/Navbar.vue
<template>
    <nav class="navbar navbar-default">
        <li>
            <router-link  to="/about">About</router-link>
        </li>
    </nav>
</template>
```

```html:resources/assets/js/components/Articles/Index.vue
<template>
    <div v-for="article in articles">
        <h1>
            <router-link :to="'/articles/' + article.id">{{ article.title }}</router-link>
        </h1>
        <p>
            {{ article.content }}
        </p>
    </div>
</template>

<script>
    export default {
        created() {
            this.fetchArticles()
        },
        data() {
            return {
                articles: []
            }
        },
        methods: {
            fetchArticles() {
                this.$http({
                    url: '/api/articles',
                    method: 'GET'
                }).then(res =>  {
                    this.articles =  res.data
                })
            }
        }
    }
</script>
```

走り書きだなあ・・・
でもこれで概念は理解できた。