タイトル: Vue.jsと連携するSPA実行環境構築
SEOタイトル: 【Laravel】Vue.jsと連携するSPA実行環境構築
この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。
<table border="1" cellpadding="1" cellspacing="1" style="width:1000px">
<thead>
<tr><th style="background-color:#f39c12;color:#ffffff;text-align:left">この記事の要点</th></tr>
</thead>
<tbody>
<tr>
<td style="background-color:#fef9e7">
<ul>
<li>Laravel + Vue.js で <strong>SPA 実行環境</strong>を構築する手順</li>
<li>Web ルーティング: Laravel 側を<strong>無効化</strong>し、すべて <code>app.blade.php</code> に集約</li>
<li>クライアントルーティング: <strong>vue-router</strong> 側で行う</li>
<li>API: <strong><code>routes/api.php</code> 経由で /api/* を使う</strong></li>
</ul>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>前提</h2>
<p>・Laravelプロジェクトを作成済み (まだの場合は<a href="https://jpn.itlibra.com/article?id=10857">こちら</a>のページを参照)</p>
<p>・Vue.jsとの連携とvue-routerのインストール (まだの場合は<a href="https://jpn.itlibra.com/article?id=21298">こちら</a>のページを参照)</p>
<p>・SPAの実行環境を構築するだけです。SPAの様々な記述方法は他のページを参照してください。</p>
<p> </p>
<h2>サーバーサイド(Laravel)のwebルーティングの無効化</h2>
<p><span style="color:#e74c3c"><strong>webのルーティング処理はVue.js側で行う</strong></span>のでLaravel側のルーティング処理は不要となる。</p>
<p><span style="color:#e74c3c">※APIのルーティング(routes/api.php)は使用する(後述)</span></p>
<p>全てにリクエストに対して共通のレイアウト(resources/views/layouts/<strong>app.blade.php</strong>)を返すようにする。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff"><span style="color:null">routes/</span><span style="color:#e74c3c">web.php</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff">Route::get('</span><span style="color:#f1c40f">/{any}</span><span style="color:#ffffff">', function () {</span></p>
<p><span style="color:#ffffff"> return view(</span><span style="color:#2ecc71">'app'</span><span style="color:#ffffff">);</span></p>
<p><span style="color:#ffffff">})</span><span style="color:#f1c40f">->where('any', '.*')</span><span style="color:#ffffff">;</span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>共通レイアウトの作成</h2>
<p>Veu.jsを使うための最低限の設定と必要なheadタグ内の要素を記述すればよい。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff">resources/views/<span style="color:#e74c3c"><strong>app.blade.php</strong></span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff"><!DOCTYPE html></span></p>
<p><span style="color:#ffffff"><html lang="{{ app()->getLocale() }}"></span></p>
<p><span style="color:#ffffff"> <head></span></p>
<p><span style="color:#ffffff"> <meta charset="utf-8"></span></p>
<p><span style="color:#ffffff"> <!-- CSRF Token --><br />
<meta name="csrf-token" content="{{ csrf_token() }}"></span></p>
<p><span style="color:#ffffff"> <!-- CSS --><br />
<link href="{{ asset('css/app.css') }}" rel="stylesheet"></span></p>
<p><span style="color:#ffffff"> </head></span></p>
<p><span style="color:#ffffff"> <body></span></p>
<p><span style="color:#f1c40f"> <div id="app"></span></p>
<p><span style="color:#f1c40f"> <router-view></router-view></span></p>
<p><span style="color:#f1c40f"> </div></span></p>
<p><span style="color:#ffffff"> <!-- Scripts --></span><br />
<span style="color:#f1c40f"> <script src="{{ mix('js/app.js') }}"></script></span></p>
<p><span style="color:#ffffff"> </body></span></p>
<p><span style="color:#ffffff"></html></span></p>
<p> </p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>サーバーサイド(Laravel)のAPIを作成</h2>
<p>テスト用にDBから適当なデータを取得するAPIを作成する。</p>
<p> </p>
<p>まずは適当なAPIルーティングを作成する。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff"><span style="color:null">routes/</span><span style="color:#e74c3c">api.php</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff">Route::get('articles', 'Article\ArticleController@getArticles');</span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>適当なコントローラーを作成する。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff">app/Http/Controllers/Article/<span style="color:#e74c3c">ArticleController.php</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff"><?php<br />
namespace App\Http\Controllers\Article;</span></p>
<p><span style="color:#ffffff">use App\Http\Controllers\Controller;<br />
use App\Models\Article;<br />
use Illuminate\Http\Request;<br />
use Log;</span></p>
<p><span style="color:#ffffff">class ArticleController extends Controller<br />
{ <br />
public function getArticles(Request $request){<br />
<br />
$articles = Article::orderBy('update_datetime', 'DESC')<br />
->limit(3)<br />
->get();<br />
<br />
return response()->json($articles);<br />
}<br />
}</span><br />
</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>適当なモデルを作成する。(マイグレーションするなり直にcreate tableしてテーブル作成をしておく)</p>
<p>※titleカラムを作成しておくこと。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff">app/model/<span style="color:#e74c3c">Article.php</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff"><?php</span></p>
<p><span style="color:#ffffff">namespace App\Models;</span></p>
<p><span style="color:#ffffff">use Illuminate\Database\Eloquent\Model;</span></p>
<p><span style="color:#ffffff">class Article extends Model<br />
{<br />
protected $table = 'article';</span></p>
<p><span style="color:#ffffff"> protected $primaryKey = 'article_id';</span></p>
<p><span style="color:#ffffff"> public $incrementing = 'article_id';</span></p>
<p><span style="color:#ffffff"> protected $guarded = [<br />
'created_at',<br />
'updated_at',<br />
];<br />
}</span><br />
</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>ローカルサーバーの起動</h2>
<p>以下の2つのコマンドをそれぞれ別窓で実行してローカルサーバーを起動する。</p>
<table border="1" cellpadding="1" cellspacing="1" style="width:1000px">
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff">php artisan serve</span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<table border="1" cellpadding="1" cellspacing="1" style="width:1000px">
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff">npm run hot</span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>Veu.jsでルーティングを作成</h2>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff"><span style="color:null">resources/assets/js/</span><span style="color:#e74c3c">app.js</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff">import Vue from 'vue'<br />
import VueRouter from 'vue-router'</span></p>
<p><span style="color:#ffffff">require('./bootstrap');</span></p>
<p><span style="color:#ffffff">Vue.use(VueRouter)</span></p>
<p><span style="color:#ffffff">const router = new VueRouter({<br />
mode: 'history',<br />
routes: [<br />
{ path: '/articles', component: require('./components/Articles.vue') },<br />
]<br />
})</span></p>
<p><span style="color:#ffffff">const app = new Vue({<br />
el: '#app',<br />
router,<br />
})</span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>ビューの作成とAPIの呼び出し</h2>
<table border="1" cellpadding="1" cellspacing="1" style="width:500px">
<thead>
<tr>
<th scope="col" style="background-color:#ffffff"><span style="color:null">resources/assets/js/components/</span><span style="color:#e74c3c">Articles.vue</span></th>
</tr>
</thead>
<tbody>
<tr>
<td style="background-color:#000000">
<p><span style="color:#ffffff"><template></span></p>
<p><span style="color:#ffffff"> <div></span></p>
<p><span style="color:#ffffff"> <ul></span></p>
<p><span style="color:#ffffff"> <li v-for="article in articles"></span></p>
<p><span style="color:#ffffff"> {{ article.title }}</span></p>
<p><span style="color:#ffffff"> </li></span></p>
<p><span style="color:#ffffff"> </ul></span></p>
<p><span style="color:#ffffff"> </div></span></p>
<p><span style="color:#ffffff"></template></span></p>
<p><span style="color:#ffffff"><script></span></p>
<p><span style="color:#ffffff"> export default {</span></p>
<p><span style="color:#ffffff"> created() {</span></p>
<p><span style="color:#ffffff"> this.getArticles()</span></p>
<p><span style="color:#ffffff"> },</span></p>
<p><span style="color:#ffffff"> data() {</span></p>
<p><span style="color:#ffffff"> return {</span></p>
<p><span style="color:#ffffff"> articles: []</span></p>
<p><span style="color:#ffffff"> }</span></p>
<p><span style="color:#ffffff"> },</span></p>
<p><span style="color:#ffffff"> methods: {</span></p>
<p><span style="color:#ffffff"> getArticles() {</span></p>
<p><span style="color:#ffffff"> axios<br />
.get('/api/articles')<br />
.then(res => {<br />
this.articles = res.data<br />
})</span></p>
<p><span style="color:#ffffff"> }</span></p>
<p><span style="color:#ffffff"> }</span></p>
<p><span style="color:#ffffff"> }</span></p>
<p><span style="color:#ffffff"></script></span></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>以上の設定で「<a href="http://localhost:8000/articles">http://localhost:8000/articles</a>」にアクセスするとarticleテーブルのtitle一覧が表示される。</p>
<p> </p>