簡介
插槽:簡單理解就是組件內部留一個或多個的插槽位置,可供組件傳對應的模板代碼進去。插槽的出現,讓組件變的更加靈活。
一、匿名插槽
// 組件(父) <my-component> <p>hello,world!</p> </my-component> // 組件內部(子) <div class="child-page"> <h1>子頁面</h1> <slot></slot> // 替換為 <p>hello,world!</p> </div> // 渲染結果 <div class="child-page"> <h1>子頁面</h1> <p>hello,world!</p> </div>
以上是最簡單的匿名插槽eg
二、具名插槽
顧名思義就是帶名字的插槽,假如需要在組件內部預留多個插槽位置,就需要為插槽定義名字,指定插入的位置。
// 組件(父) <my-component> <template v-slot:header> <p>頭部</p> </template> <template v-slot:footer> <p>腳部</p> </template> <p>身體</p> </my-component> // 組件內部(子) <div class="child-page"> <h1>子頁面</h1> <slot name="header"></slot> <slot></slot> // 等價於 <slot name="default"></slot> <slot name="footer"></slot> </div> // 渲染結果 <div class="child-page"> <h1>子頁面</h1> <p>頭部</p> <p>身體</p> <p>腳部</p> </div>
vue >=2.6.0版本,使用v-slot替代slot 和 slot-scope。
注意三點
- 具名插槽的內容必須使用模板<template></template>包裹
- 不指定名字的模板插入匿名插槽中,推薦使用具名插槽,方便代碼追蹤且直觀清楚
- 匿名插槽具有隱藏的名字"default"
三、具名插槽的縮寫和動態插槽名
具名插槽縮寫
<my-component> <template #header> <p>頭部</p> </template> <template #footer> <p>腳部</p> </template> <template #body> <p>身體</p> </template> </my-component>
動態插槽名
<my-component> <template #[headerPart]> // v-slot:[headerPart] <p>頭部</p> </template> <template #footer> <p>腳部</p> </template> <template #body> <p>身體</p> </template> </my-component> ... data() { return { headerPart: 'header' } }
四、插槽參數傳遞
父傳子
// 組件(父) <my-component :title="'我是'" > <template #header> <p>頭部</p> </template> <template #footer> <p>腳部</p> </template> <template #body> <p>身體</p> </template> </my-component> // 組件內部(子) <div class="child-page"> <h1>{{title}}子頁面</h1> <slot name="header"></slot> <slot name="body"></slot> <slot name="footer"></slot> </div> props: { title: { type: String } }
以下這種傳參是錯誤的
<my-component :title="'我是'" > <template #header> <p>{{title}}頭部</p> // 錯誤 </template> <template #footer> <p>腳部</p> </template> <template #body> <p>身體</p> </template> </my-component>
所以如果需要動態修改插槽的內容,就需要子組件傳參給父組件。
子傳父
// 組件(父)傳參並接受參數 <my-component v-bind="layout" // 傳遞參數 > // 可以使用ES6解構{ slotProps } <template #header="slotProps"> // 接受參數 <p>{{slotProps.headers}}</p> </template> <template #footer="slotProps"> <p>{{slotProps.footers}}</p> </template> <template #body="slotProps"> <p>{{slotProps.bodys}}</p> </template> </my-component> ... data() { return { layout: { header: '頭部', body: '身體', footer: '腳部' } } } // 組件內部(子) <div class="child-page"> <h1>子頁面</h1> <slot name="header" :headers="header"></slot> <slot name="body" :bodys="body"></slot> <slot name="footer" :footers="footer"></slot> </div> ... props: { header: { require: true }, body: { require: true }, footer: { require: true } }
總結:
父組件傳參給子組件,props接收后,插槽slot再通過綁定屬性傳遞參數返回給父組件,不管是模板代碼還是數據,控制權完全掌握在父組件手里。