【Laravel】bladeの@includeと@componentの違い

bladeの`@include`と`@component`を使い分けるためのメモ。
結論だけ述べると、どちらを使っても同じ見た目は作れる。
`@include`はタグの数が決まっている場合と相性がよく、
`@component`はタグの数が不定の場合と相性が良い。

#前提
バージョン：Laravel6

#`@include`の使い方
```php:
@include('読込ファイル', ['変数名' => '代入値',...])
```
`読込ファイル`内に変数が存在するときは第２引数で指定することで値を渡すことができる。

#`@component`の使い方
```php:
@component('読込ファイル', ['変数名' => '代入値',...])
    /* {{ $slot }}に入る内容 */

    @slot('スロット名')
        /* {{ $スロット名 }}に入る内容 */
    @endslot
@endcomponent
```
`読込ファイル`内に変数が存在するときは第２引数で指定することで値を渡すことができる。
また`@component`内に書いた内容は`読込ファイル`内の`{{ $slot }}`へと挿入される。`@slot`を使用することで任意の変数名にすることも可能。

#使い分け例
##①ボタンの使い回し
例えば同じ見た目のボタンを表示名と色を変えて使いまわすことを考える。

```php:button.blade.php
<button type="button" class="btn btn-{{ $color }}">{{ $name }}</button>
```

```php:view.blade.php
<div class="m-3">
    <p>includeで作成</p>
    @include('button',[
        'color' => 'primary',
        'name' => 'ボタン1'
    ])

    @include('button',[
        'color' => 'success',
        'name' => 'ボタン2'
    ])

    @include('button',[
        'color' => 'danger',
        'name' => 'ボタン3'
    ])
</div>
<div class="m-3">
    <p>componentで作成</p>
    @component('button',[
        'color' => 'primary',
        'name' => 'ボタン1'
    ])
    @endcomponent

    @component('button',[
        'color' => 'success',
        'name' => 'ボタン2'
    ])
    @endcomponent

    @component('button')
        @slot('color')
            danger
        @endslot
        @slot('name')
            ボタン3
        @endslot
    @endcomponent
```

結果は下の画像の通り。
![ボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/08d8acdd-b229-92dd-77af-99eea7c7d04c.png)
例のように決まった要素数のものを使いまわすのであれば、`@include`も`@component`も大して変わらない書き方になる。
`@component`では`@endcomponent`を書くため微妙に`@include`の方が見やすいかもしれない。
また、`@component`は変数で渡すかスロットとして取り込むかで2通りの書き方がある。


##②レイアウトの使い回し
例えば、コンテンツを配置する枠は使いまわすけれど、中身は不定という場合を考える。

```php:frame.blade.php
<div class="container-fluid my-3">
    <h3 class="text-white text-center bg-dark rounded-top m-0">
        {{ $title }}
    </h3>
    <div class="border border-dark rounded-bottom p-2">
        {{ $slot }} // includeの場合は{!! $slot !!}
    </div>
</div>
```

```php:view.blade.php
<div class="m-3">
    <p>includeで作成</p>
    @include('frame', [
        'title' => 'テキスト',
        'slot' => '<p>これはテキストです。</p>',
    ])

    @php
        $list = '';
        for($i = 1; $i <= 5; $i++) {
        $list = "$list<li class='list-group-item'>アイテム$i</li>";
        }
    @endphp
    @include('frame', [
        'title' => 'リスト',
        'slot' => $list,
    ])
</div>

<div class="m-3">
    <p>componentで作成</p>
    @component('frame', ['title' => 'テキスト'])
        <p>これはテキストです。</p>
    @endcomponent

    @component('frame', ['title' => 'リスト'])
        <ul class="list-group">
            @for($i = 1; $i <= 5; $i++)
                <li class="list-group-item">アイテム{{ $i }}</li>
            @endfor
        <ul>
    @endcomponent
</div>
```
結果は下の画像の通り。
![フレーム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/2101077e-7e59-1cff-93c1-6ca8fc375d58.png)

要素数や種類が変わる場合には`@include`では変数に格納するために見づらい書き方をとらざるをえない。変数として渡すため、制御構文を使いたければ外側に書く必要がある。
`@component`では要素や制御構文をそのままの形で使用できるため整った見た目になる。

なお、`@include`に要素を渡すときに`{{ }}`のままではエスケープされてしまう（下記画像）。正しく表示するには`{!! !!}`にしなければならない。
![フレーム２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401303/ed959ef4-284a-8a1c-3fe3-a36b6cb5a011.png)

#結論
制御構文を使ったり、内容となるhtml要素に自由度を持たせたい場合は`@component`を使うとで見やすいコードとなる。
一方、制御構文を使わない（使うとしても渡すのは構文内の変数だけ）であったり、内容となるhtml要素は固定で表示内容や属性に変数を渡すだけの場合は`@include`を使うとで見やすいコードとなる。
表示結果についてはどちらを使っても同じものは実装できる。