前言

關於 Laravel Blade Component 的介紹,官方文件寫得很清楚,這邊簡單的介紹常見用法,並且提供一些實際的使用案例。

簡介

Laravel Blade Component 是在 Laravel 7.0 版本中新增的功能,主要是用來取代原本的 Blade include,讓我們可以更方便的將重複的 HTML 結構抽出來,並且可以透過 Blade Component 的方式來使用,以下分別介紹兩種元件元件匿名元件

元件

標準的元件形式,相較匿名元件複雜一點,但是可以更好的管理元件的參數與HTML結構。

建立元件

1
php artisan make:component Input

建立元件後,會在 app/View/Components 中建立一個 Input.php,並且在 resources/views/components 中建立一個 input.blade.php
接著我們就可以在 Input.php 中定義元件的參數,並且在 input.blade.php 中定義元件的 HTML 結構。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// app/View/Components/Input.php
<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Input extends Component
{
public $title;

// 在建構子中定義元件的參數
public function __construct($title)
{
$this->title = $title;
}

public function render()
{
return view('components.input'); // 指定需使用的元件檔案
}
}

元件內我們定義了HTML結構,並且使用在Input.php中定義的參數。

1
2
3
4
5
6
// resources/views/components/input.blade.php
<div class="input">
<div class="input-heading">
{{ $title }}
</div>
</div>

使用時,我們先依到元件名稱建立元件標籤x-{元件名稱},並且用屬性傳入title參數。

使用元件

在 Blade 中使用元件可以使用以下方式:

1
<x-input title="姓名" />

實際輸出結果:

1
2
3
4
5
<div class="input">
<div class="input-heading">
姓名
</div>
</div>

這時會可能有人會好奇,元件名稱是依照app/View/Components中檔案名稱還是resources/views中的blade檔案名稱呢?在撇除之後要談到的匿名元件前提下,這邊的元件名稱是依照app/View/Components中檔案名稱,並且使用kebab-case的方式來命名。

匿名元件

相較於元件匿名元件的使用方式更為簡單,但是使用上比較不靈活,因為沒有中間元件檔案詳細管理參數與邏輯。

建立元件

因為指令建立會建立元件檔案,所以這邊我們直接在resources/views/components中建立一個select.blade.php
其中@props是用來定義元件的參數,也可以給預設值,讓屬性為非必填。

1
2
3
4
5
6
7
8
9
10
// resources/views/components/select.blade.php
@props([
'title'
])

<div class="input">
<div class="input-heading">
{{ $title }}
</div>
</div>

使用時,我們直接在x-{元件名稱}中使用props來定義元件的參數,並且在元件標籤中使用屬性傳入參數。

使用匿名元件

在 Blade 中使用匿名元件可以使用以下方式:

1
<x-select title="姓名" />

實際輸出結果:

1
2
3
4
5
<div class="input">
<div class="input-heading">
姓名
</div>
</div>

匿名元件命名方式是依照resources/views中的blade檔案名稱,並且一樣使用kebab-case的方式來命名。
這邊額外補充一個觀念,假設同時有相同名稱的元件匿名元件,在使用時會優先使用元件。但是還是建議不要有相同名稱的元件匿名元件,以免造成混淆。

元件用法

以下用法是共通的,不論是元件或是匿名元件都可以使用。

Slot

我們可以透過 $slot Laravel元件中內建的變數來傳遞子元件(或任意HTML)給父元件,這邊我們將 input Content 傳遞給子元件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// resources/views/components/input.blade.php
<div class="input">
<div class="input-heading">
{{ $title }}
</div>

<div class="input-body">
{{ $slot }}
</div>
</div>

// use component
<x-input title="input Title">
input Content
</x-input>

// output
<div class="input">
<div class="input-heading">
input Title
</div>

<div class="input-body">
input Content
</div>
</div>

傳遞參數給子元件

假設我想要在子元件中使用父元件的參數,會有兩種情況:

  1. 子元件寫在父元件中
    這種方法就能直接使用父元件的參數,傳入子元件中,像是title。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // resources/views/components/parent-input.blade.php
    <div class="input">
    <div class="input-heading">
    <x-child-input :title="$title" />
    </div>
    </div>

    // resources/views/components/child-input.blade.php
    <div class="input-heading">
    {{ $title }}
    </div>

    // use component
    <x-parent-input title="parent Title" />

    // output
    <div class="input">
    <div class="input-heading">
    <div class="input-heading">
    parent Title
    </div>
    </div>
  2. 子元件使用slot傳入父元件
    如果使用slot動態傳入子元件,必須使用@aware,並且定義父元件參數名稱,就能接收父元件的參數。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // resources/views/components/parent-input.blade.php
    <div class="input">
    <div class="input-heading">
    {{ $slot }}
    </div>
    </div>

    // resources/views/components/child-input.blade.php
    @aware(['title'])

    <div class="input-heading">
    {{ $title }}
    </div>

    // use component
    <x-parent-input title="parent Title" />
    <x-child-input />
    </x-parent-input>

    // output
    <div class="input">
    <div class="input-heading">
    <div class="input-heading">
    parent Title
    </div>
    </div>
    </div>

參數$attributes各種用法

$attributes是Laravel元件中內建的變數,包含所有傳入元件的參數與用法。
這邊我們可以透過$attributes來合併class或是其他屬性。

  • merge:合併class或是其他屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->merge(['class' => 'input']) }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" />

    // output
    <div class="input input-class">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • class:合併class。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->class(['input']) }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" />

    // output
    <div class="input input-class">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • except:排除特定屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->except(['class']) }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div id="input-id">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • only:只取特定屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->only(['class']) }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div class="input-class">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • get:取得特定屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->get('class') }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div class="input-class">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • set:設定特定屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->set('class', 'input') }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div class="input">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • has:判斷是否有特定屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->has('class') ? 'class="input"' : '' }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div class="input">
    <div class="input-heading">
    input Title
    </div>
    </div>
  • all:取得所有屬性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // resources/views/components/input.blade.php
    <div {{ $attributes->all() }}>
    <div class="input-heading">
    {{ $title }}
    </div>
    </div>

    // use component
    <x-input title="input Title" class="input-class" id="input-id" />

    // output
    <div class="input input-class" id="input-id">
    <div class="input-heading">
    input Title
    </div>
    </div>

結語

這邊簡單的介紹一下 Laravel Blade Component 的常用使用方式,如果想要更深入的了解,可以參考官方文件:https://laravel.com/docs/10.x/blade#components
如果有任何問題或是建議,歡迎在下方留言,謝謝!