[Laravel 5.4][Features] Components và slot trong Laravel 5.4

Spread the love

Laravel 5.4 được bổ sung thêm một directive mới là @component và trong bài này chúng ta sẽ cùng đi tìm hiểu , nó là gì và áp dụng vào đâu

Giới thiệu về @component và @slots trong blade


Khái niệm về slot:

Slot là một khái niệm có lẽ được mượn từ phía Vue.js, ở đó Slot được định nghĩa như là một nút phân tán (distribution outlet) cho component . Hiểu nôm na là component có thể được cấu thành tự rất nhiều thành phần, trong đó thành phần nguyên tử và không thể chia nhỏ hơn được nữa ta sẽ gọi là slot

Ok. Chắc các bạn sẽ không hiểu gì cả :))). Nào chúng ta cùng xem đoạn code bên dưới:

<div>
 <h1>I'm the parent title</h1>
 <my-component>
 <p>This is some original content</p>
 <p>This is some more original content</p>
 </my-component>
</div>

Dựa theo đoạn code trên thì slot chính là 2 thẻ <p>.

Tất nhiên chúng ta có thể có nhiều slot bên trong component, và tất nhiên là ta sẽ phải đặt tên cho từng slot của mình.

 <app-layout>
    <h1 slot="header">Here might be a page title</h1>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
    <p slot="footer">Here's some contact info</p>
</app-layout>

Bên trên ta đã thấy cáche Vue.JS áp dụng slot , và component của laravel cũng sẽ ứng dụng tương tự như vậy.

Cách Apply Component vào blade

Ok. Tiếp theo chúng ta sẽ thử tìm cách apply component vào blade.

Chúng ta sẽ khai báo component bằng cách @component('component_name', [vars]) .... @endcomponent , trong đó nằm giữa chính là slot vô danh, tất nhiên ta có thể đặt tên cho slot và truyền vào như bên dưới @slot('slot_name').... @endslot . Và nếu viết lại đoạn Vue.js ở trên theo phong cách blade thì ta sẽ viết lại như bên dưới.

<div>
 <h1>I'm the parent title</h1>
 @component('my-component')
 <p>This is some original content</p>
 <p>This is some more original content</p>
 @endcomponent
</div>

my-component : như bên dưới

<div>
 <h2>I'm the child title</h2>
 {{ $slot }}
</div>

Nhìn cách viết cũng có vẻ như Vue.js

Có thể chúng ta sẽ lo lắng là không biết có tag html bên trong my-component có ổn không ? Câu trả lời là ổn, không sao cả 🙂

Nếu slot có tên thì ta có thể viết lại thành như bên dưới


@component('app.layout')
 @slot('header')
 <h1>Here might be a page title</h1>
 @endslot
 <p>A paragraph for the main content.</p>
 <p>And another one.</p>
 @slot('footer')
 <p>Here's some contact info</p>
 @endslot
@endcomponent

Code của component như bên dưới


<div class="container">
 <header>
   {{ $header }}
 </header>
 <main>
   {{ $slot }}
 </main>
 <footer>
   {{ $footer }}
 </footer>
</div>

Output của chúng ta


<div class="container">
 <header>
   <h1>Here might be a page title</h1>
 </header>
 <main>
   <p>A paragraph for the main content.</p>
   <p>And another one.</p>
 </main>
 <footer>
   <p>Here's some contact info</p>
 </footer>
</div>

Tiếp theo giả sử ta có muốn truyền động link vào trong 1 component như bên dưới

<a class="btn btn-primary" href="{{ $url }}">{{ $slot }}</a>

Thì ở view gọi đến component button ta có thể truyền như bên dưới

<body>
        @component('button', ['url' => "http://sos.com"])
            Send an SOS Signal
        @endcomponent
    </body>

Tuy nhiên nếu, ta không truyền array có key là url thì điều gì sẽ xảy ra ?

<body>
        @component('button', [])
            Send an SOS Signal
        @endcomponent
    </body>

Lỗi bên dưới sẽ xuất hiện

Vì vậy , khi dùng slot hãy nhớ set default cho từng slot (giả sử nếu bạn có quên set thì cũng không bị exception xảy ra).

Ta có thể chỉnh lại component như bên dưới

<a class="btn btn-primary" href="{{ $url or "http://www.sos.com" }}">{{ $slot }}</a>

 

Kết luận


Slots giúp chúng ta có thể chia nhỏ các components của view, giúp ta tái sử dụng được code một cách tối ưu hơn. Ngoài ra còn giúp cho code của view có rõ ràng và mạch lạc hơn, nếu được thì chúng ta cùng nhau áp dụng nó vào dự án của hiện tại của mình nhé.

Leave a Reply

Your email address will not be published. Required fields are marked *