Vue Component 之 Slot
關於顯示於 Component 的 data,除了使用 prop 傳遞外,也可使用 slot 傳遞。
Version
Vue 2.5.17
Vue CLI 3.0.3
Slot Content
1 | <navigation-link url="/profile"> |
在自己寫了 component 間夾了 data。
1 | <a v-bind:href="url"class="nav-link"> |
在 component 的 HTML template 中使用 <slot></slot>
,則 component 間夾的 data 將取代 <slot></slot>
。
若 HTML template 內沒有
<slot></slot>
,則 data 將不會顯示
最後 HTML 為:
1 | <a v-bind:href="url"class="nav-link"> |
<slot></slot>
可視為 placeholder,專門顯示 component tag 間的 data,如此就不必什麼 data 都靠 prop 傳遞。
Slot 可是為傳遞 data 的另外一種方式,尤其是
顯示型
的 data
1 | <navigation-link url="/profile"> |
Component tag 間不單只能放 data,也可以放其他 HTML。
1 | <navigation-link url="/profile"> |
Component tag 間也可以放其他 component。
Named Slot
Vue 也允許在一個 component 間有多個 slot,此時必須使用 Named Slot。
1 | <div class="container"> |
我們希望 base-layout
component 的 header
、main
與 footer
三部分都使用 slot,由 user 提供 data。
一個 component 只能有一個 default slot,其他都必須是 named slot
所以在 header
與 footer
使用了 named slot,在 <slot></slot>
多了 name
,設定 slot 的名稱為 header
與 footer
。
main
則使用 default slot,不特別為 slot 取名稱。
1 | <base-layout> |
使用 base-layout
component 時,由於有多個 slot,要搭配 template
tag 將 data 與 HTML 包起來,並使用 slot
attribute 指定 slot 名稱。
沒使用 template
tag 部分,則為 default slot。
1 | <base-layout> |
也可以直接對 HTML 加上 slot
attribute。
最後 HTML 為:
1 | <div class="container"> |
3 個 slot 完全被取代。
Default Slot Content
Slot 雖然目的就是由 user 提供 data 顯示,但有時候會想在 component 內提供預設顯示 data。
1 | <button type="submit"> |
submit-button
component 預設顯示 Submit
,但也允許 user 提供其他 data 顯示,如 Save
與 Upload
,就可在 <slot>
與 </slot>
之間夾預設顯示 data。
Scoped Slot
若想由 user 自訂 slot,但實際 data 卻是在 component 內,此時就要使用 Scoped Slot。
1 | <ul> |
todo-list
component 雖然已經提供 todo.title
的顯示,但為了讓 component 更有彈性,想提供 slot 由 user 能夠提供不同顯示方式。
1 | <ul> |
將 todo
以 prop 方式傳進 slot,此為預設顯示方式。
1 | <todo-list :todos="todos"> |
User 提供了不同的顯示方式取代 slot。
在 <template>
加上 slot-scope
attribute 指定 scope 名稱,然後使用 scope 名稱存取 component 內的 data。
不一定得使用
<template>
tag,任何 HTML tag 加上slot-scope
皆可
1 | <todo-list :todos="todos"> |
若搭配 ECMAScript 2015 的 Object Destructuring,則有更好的寫法。
因為 slotProps
本質就是有 todo
property 的 object。
可使用 { todo }
將 todo
取出為變數直接使用,則不必在定義 slotProps
這種中介變數。
Conclusion
- 有了 Slot,顯示型的 data 就不必再使用 prop,可直接使用 slot 傳遞
- 若 component 提供多個 slot,則要使用 Named Slot
- Slot 也可提供預設顯示 data
- 若想提供 user 自訂 slot,卻要讀取 component 內的資料,則要使用 Scoped Slot;若搭配 ECMAScript 2015 的 Object Destructuring 寫法,則非常精簡
Sample Code
完整的範例可以在我的 GitHub 上找到