1. Slots là gì ?
Slots là một kỹ thuật Vue Components
cho phép bạn đặt nội dụng ở một vị trí mới hoặc tạo ra những component chung. Cách tốt nhất để hiểu Slots hoạt động như thế nào ?. Tôi sẽ đưa ra những khái niệm tới việc vận dụng nó vào những trường hợp nào bạn sẽ thấy trực quan khi làm dự án.
Hãy cùng tôi bắt đầu một ví dụ đơn giản:
(1)
1 2 3 4 5 6 7 | <span class="token comment">// Button.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>button <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"btn-wrapper"</span><span class="token operator">></span> <span class="token operator"><</span>slot <span class="token operator">/</span><span class="token operator">></span> <span class="token comment">// Vị trí giữa thẻ đóng/mở của Button sẽ được thay thế vào đây.</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
(2)
1 2 3 4 5 6 7 | <span class="token comment">// App.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>div id<span class="token operator">=</span><span class="token string">"app"</span><span class="token operator">></span> <span class="token operator"><</span>Button<span class="token operator">></span>Submit<span class="token operator"><</span><span class="token operator">/</span>Button<span class="token operator">></span> <span class="token comment">// text 'Submit' sẽ được thay vào vị trí của slot tag trong Button component.</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
Bạn cũng có thể để một nội dung mặc định khi mà bạn không thêm gì vào giữa thẻ đóng/mở của Button component
Tôi sửa một chút ở code:
(1)
1 2 3 4 5 6 7 | <span class="token comment">// Button.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>button <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"btn-wrapper"</span><span class="token operator">></span> <span class="token operator"><</span>slot<span class="token operator">></span>Default Content<span class="token operator"><</span><span class="token operator">/</span>slot<span class="token operator">></span> <span class="token comment">// Vị trí giữa thẻ đóng/mở của Button không có sẽ hiển thị nội dung này.</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
(2)
1 2 3 4 5 6 7 | <span class="token comment">// App.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>div id<span class="token operator">=</span><span class="token string">"app"</span><span class="token operator">></span> <span class="token operator"><</span>Button<span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>Button<span class="token operator">></span> <span class="token comment">// Nội dung thẻ đóng/mở không có.</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
2. Multiple/Named Slots
Bạn có thể thêm nhiều slot vào trong một component. Nếu làm cách này thì bạn cần cung cấp name
cho mỗi slot
. Nếu như slot
nào không có name
, nó là default slot
. Ví dụ để tạo multiple slots
.
1 2 3 4 5 6 7 8 | <span class="token comment">// Card.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"card-wapper"</span><span class="token operator">></span> <span class="token operator"><</span>slot name<span class="token operator">=</span><span class="token string">"title"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token comment">// Ở đây sẽ render nội dụng của (1) có v-slot:title trong App .</span> <span class="token operator"><</span>slot <span class="token operator">/</span><span class="token operator">></span> <span class="token comment">// Ở đây sẽ render nội dung của (2).</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token comment">// App.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>div id<span class="token operator">=</span><span class="token string">"app"</span><span class="token operator">></span> <span class="token operator"><</span>Card<span class="token operator">></span> <span class="token operator"><</span>template v<span class="token operator">-</span>slot<span class="token operator">:</span>title<span class="token operator">></span> <span class="token comment">// sử dụng v-slot directive để biết được là phần code trong `template` sẽ được thêm vào slot có name="title" trong Card component (1).</span> <span class="token operator"><</span>h1<span class="token operator">></span>Title<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> <span class="token operator"><</span>div<span class="token operator">></span>Content<span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token comment">// render trong default slot (2).</span> <span class="token operator"><</span><span class="token operator">/</span>Card<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
3. Scoped Slot
Một điều bạn cần biết là bạn có thể truyền data/function từ children component
lên parent component
. Để giải thích cái này, chúng ta sẽ tạo một CurrentUser
component:
1 2 3 4 5 6 7 8 9 | <span class="token comment">// CurrentUser.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>span<span class="token operator">></span> <span class="token operator"><</span>slot v<span class="token operator">-</span>bind<span class="token operator">:</span>user<span class="token operator">=</span><span class="token string">"user"</span><span class="token operator">></span> <span class="token comment">// bind data vào slot.</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> user<span class="token punctuation">.</span>firstName <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>slot<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>template<span class="token operator">></span> |
1 2 3 4 5 6 7 8 9 | <span class="token comment">// App.vue</span> <span class="token operator"><</span>template<span class="token operator">></span> <span class="token operator"><</span>div id<span class="token operator">=</span><span class="token string">"app"</span><span class="token operator">></span> <span class="token operator"><</span>CurrentUser v<span class="token operator">-</span>slot<span class="token operator">:</span><span class="token keyword">default</span><span class="token operator">=</span><span class="token string">"slotProps"</span><span class="token operator">></span> <span class="token comment">// Lấy data từ slot.</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> slotProps <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token comment">// Xem slotProps có gì nhé.</span> <span class="token operator"><</span><span class="token operator">/</span>CurrentUser<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span>template<span class="token operator">></span> |
Một số lưu ý:
slotProps
bạn có thể thay thế bằng một cái tên mà bạn muốn.- Nếu bạn chỉ sử dụng
default slot
, bạn có thể bỏtemplate
tag and đặtv-slot
directive vào trực tiếpCurrentUser
tag. - Bạn có thể sử dụng
Object Destructuring
để tạo tham chiếu trực tiếp tới data thay vì sử dụng một tên biến:v-slot="slotProps"
=>v-slot="{ user }"
. - Nếu
default slot
bạn có thể viết thành:v-slot:default="slotProps"
=>v-slot="slotProps"
. v-slot
có thể viết tắt#
.- default slot:
v-slot="slotProps"
=>#default="shotProps"
. - named slot:
v-slot:title="slotProps"
=>#title="shotProps"
.
- default slot:
Nếu thấy bài viết bổ ích đối với bạn khi mới học Vue thì cho mình 1 vote nhé [email protected]#$%^&*