【Laravel】 blade.phpファイルの中でvueを書く

## 環境

- Laravel: 8.6.2
- Vue.js: 2.6.12
- PHP: 8.0.8
- Composer: 2.5.1
- Node.js: 19.3.0

```zsh
$ composer create-project --prefer-dist laravel/laravel:^8.0 project-name
$ cd project-name
$ php artisan migrate:fresh
$ composer require laravel/ui
$ php artisan ui vue --auth
$ npm install && npm run dev
$ php artisan serve
```

`--auth`とするとViewが用意されていて楽なので、この記事では既に用意されているhome.blade.phpに追記する形で、動かしていきたいと思います。

### Tips.認証機能の無効化

環境構築時に`php artisan ui vue --auth`としたのは、新たに追加されるapp.blade.phpとhome.blade.phpを使うためです。
しかし、一々このためにregister,login処理をするのも面倒なので、以下のコードをコメントアウトしておくとURLに`/home`と入力するだけで検証結果が確認できるようになります。

```php:web.php
Route::get('/', function () {
    return view('welcome');
});

// Auth::routes(); <- コメントアウト
 
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
```

```php:HomeController
    public function __construct()
    {
        // $this->middleware('auth'); <- コメントアウト
    }
```


## 1.resource/views/layouts/app.blade.phpにyieldを追加する

そこでhome.blade.phpを見てみると、**layouts.appを継承**していることがわかるので、継承元のlayouts.appにscriptを記述するためのyieldを追加します。

```php:app.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>

~~~~

        <main class="py-4">
            @yield('content')
        </main>
    </div>
@yield('js')  <-- ここに追加
</body>
</html>
```

なお下記のように、scriptタグの中に入れても問題ありません(むしろそうしたい！)。

```php
        <main class="py-4">
            @yield('content')
        </main>
    </div>
  <script>
  @yield('js')  <-- ここに追加
  </script>
</body>
</html>
```

ただその場合、vueを記述する側のhome.blade.phpで補完やハイライト等**エディタの恩恵が受けられなくなってしまいます**。
したがって継承元のlayouts.appではscriptタグには入れていません。

## 2. resource/views/home.blade.phpにscriptを追加する

```php:home.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Vueお試し</div>

                <div class="card-body">
                    <input v-model="name">
                    <p>名前： @{{ name }}</p>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

@section('js')
<script>
    const app = new Vue({
        el: '#app',
        data: () => {
            return {
                name: '',
            }
        },
        methods: {}
    });
</script>
@endsection
```

inputに入力されたものをpタグに表示する、v-modelを使用したシンプルなものを用意しました。
ただこのままではうまく行きません。

```console
home:66 Uncaught ReferenceError: Vue is not defined
    at home:66:17

app.js:33420 [Vue warn]: Property or method "name" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

(found in <Root>)
```

これは既にapp.jsでVueインスタンスが作成されていることに起因しています。
次はこの問題を解消しましょう🤔

## 3.個々のblade.phpでそれぞれのVueインスタンスを作成する

まずapp.jsを修正します。

```js:app.js
require('./bootstrap');

window.Vue = require('vue').default;
```

次にapp.blade.phpでapp.jsを読み込んでいる部分のdeferを削除します。

```php:app.blade.php
// デフォルトで13行目
<script src="{{ asset('js/app.js') }}"></script>
```

:::note info
deferの役割については[ココ!](https://ja.javascript.info/script-async-defer)からご確認ください☕️
:::

最後に、プロジェクトルートで`npm run dev`を入力してください。
これでhome.blade.phpにvueが記述できるようになったことが確認できます。
他のblade.phpについても、layouts.appを継承していれば、同様の方法でVueを記述することができます👍


## end.Githubのリポジトリ

今回作成したコードは以下のリポジトリに載せてあります。

https://github.com/bayuTiger/laravel-blade-vue