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 上找到