前言:v-slot 指令自 2.6.0 起被引入,提供更好的支持 slot 和 slot-scope 特性的 API 替代方案。在接下來所有的 2.x 版本中 slot 和 slot-scope 特性仍會被支持,但已經被官方廢棄且不會出現在 Vue 3 中。
slot(已廢棄)
①內容:假如父組件需要在子組件內放一些DOM,那么這些DOM是顯示、不顯示、在哪個地方顯示、如何顯示,就是slot分發負責的活
②默認情況下,該組件起始標簽和結束標簽之間的任何內容都會被拋棄
//父組件 <template> <div id="app"> <son>我想顯示點內容</son> </div> </template> //子組件 <template> <div> <span>我是子組件</span> </div> </template>
③單個slot:當父組件需要顯示一些東西在子組件里時,只需要將這個<slot>放置於子組件想要顯示的地方即可,若沒有name,則為默認插槽(匿名插槽),一個不帶name
的<slot>
出口會帶有隱含的名字“default”。
//父組件 <template> <div id="app"> <son>
<div>我顯示出來了</div>
</son> </div> </template> //子組件 <template> <div> <p><slot></slot></p> <p>我是子組件</p> </div> </template>
上述代碼中父組件等同於下面的代碼,兩者之間的區別是是否將隱含的“default”寫出來
//父組件 <template> <div id="app"> <son> <div slot="default">我顯示出來了</div> </son> </div> </template>
④多個slot:當需要多個插槽顯示在不同的地方時,需要給每個插槽加上一個name,並且父組件內加上"slot=name",使兩者之間具有有關聯性,這就是具名插槽
//父組件 <template> <div id="app"> <son> <div slot="slotOne">我是插槽一</div> <div slot="slotTwo">我是插槽二</div> <div slot="slotThree">我是插槽三</div> </son> </div> </template> //子組件 <template> <div> <p><slot name="slotOne"></slot></p> <p><slot name="slotTwo"></slot></p> <p class="content">我是子組件</p> <p><slot name="slotThree"></slot></p> </div> </template>
注:多個插槽也能有且最多只能一個默認插槽
⑤當沒有對應插槽的name時
1)插槽里沒有默認的內容,則會什么的都不輸出
//父組件 <template> <div id="app"> <son> <div>我想插入進去</div> </son> </div> </template> //子組件 <template> <div> <p class="content">我是子組件</p> <p><slot name="slotOne"></slot></p> </div> </template>
2)插槽內有默認內容,則會直接輸出插槽內的內容
//父組件 <template> <div id="app"> <son> <div>我想插入進去</div> </son> </div> </template> //子組件 <template> <div> <p class="content">我是子組件</p> <p><slot name="slotOne">沒有對應name時,我會顯示</slot></p> </div> </template>
⑥當具名插槽和默認插槽混合使用的時候,任何沒有包裹slot(或者slot="default")的都將視為默認插槽的內容,對於包裹相同slot值的標簽會渲染在同一個位置
//父組件 <template> <div id="app"> <son> <div>匿名插槽第一段內容</div> <div slot="slotOne">相同具名一</div> <div>匿名插槽第二段內容</div> <div slot="slotOne">相同具名二</div> 匿名插槽第三段內容 </son> </div> </template> //子組件 <template> <div> <p style="border:1px solid #0ff"><slot></slot></p> <p style="border:1px solid #f00"><slot name="slotOne"></slot></p> </div> </template>
slot-scope(已廢棄)
本文所有作用域插槽,子組件里news的數據
<script> export default { name: "name", data(){ return{ news:[ '十九屆四中全會28日至31日在京召開', '珍愛和平團結合作 構建人類命運共同體', '法治是最好的營商環境', '夯實優化營商環境的法治基石', '中國營商環境全球排名再前進15名!' ], } } } </script>
①作用域插槽或者說是一個帶數據的插槽
//父組件 <template> <div id="app"> <son> <template slot="news" slot-scope="newsData"> <ul> <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li> </ul> </template> </son> </div> </template> //子組件 <template> <div> <p class="content">我是子組件</p> <p><slot name="news" :newsList = 'news'></slot></p> </div> </template>
這里有小坑:
1)這里的 slot-scope
聲明了被接收的 prop 對象會作為 newData
變量存在於 <template>
作用域中。你可以像命名 JavaScript 函數參數一樣隨意命名 newData
。
2)這時的newData數據結構為:
newsData:{ newsList:[ '十九屆四中全會28日至31日在京召開', '珍愛和平團結合作 構建人類命運共同體', '法治是最好的營商環境', '夯實優化營商環境的法治基石', '中國營商環境全球排名再前進15名!' ] }
3)slot-scope
特性也可以直接用於非 <template>
元素
<template> <div id="app"> <son> <div slot="news" slot-scope="newsData"> <ul> <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li> </ul> </div> </son> </div> </template>
②slot-scope接收到的值也可以使用ES6解構
<template> <div id="app"> <son> <div slot="news" slot-scope="{news}"> <ul> <li v-for="(item,index) in news" :key="index">{{item}}</li> </ul> </div> </son> </div> </template>
v-slot
重點來了,v-slot是 v2.6.0 引入的新的指令,目的是為了更好的支持slot、slot-scope的特性(其實就是把兩個統一起來),新人上位,老人就應該退居幕后,並輔佐一段時間,所以slot、slot-scope在v2.6.0正式廢棄(后續的2.x版本依舊支持,但不推薦),在將來的v3.x版本中正式廢除(就是3.x版本不支持不能用了)
①默認插槽寫法和以前沒什么變化,v-slot主要針對具名插槽、作用域插槽
②具名插槽,v-slot:name
//父組件 <template> <div id="app"> <son> <template v-slot:slotOne>我想顯示一點內容</template> </son> </div> </template> //子組件 <template> <div> <p><slot name="slotOne"></slot></p> </div> </template>
這里有小坑
1)除獨占默認插槽的縮寫語法外,v-slot
只能添加在一個 <template>
上
③作用域插槽,v-slot:name = customName
綁定在 <slot>
元素上的特性被稱為插槽 prop。現在在父級作用域中,我們可以給 v-slot
帶一個值來定義我們提供的插槽 prop 的名字
//父組件 <template> <div id="app"> <son> <template v-slot:news = "newsData"> <ul> <li v-for="(item,index) in newsData.newsList" :key="index"> {{index}}、{{item}} </li> </ul> </template> </son> </div> </template> //子組件 <template> <div> <p><slot name="news" :newsList = 'news'></slot></p> </div> </template>
在這個例子中,我們選擇將包含所有插槽 prop 的對象命名為 newsData
,但你也可以使用任意你喜歡的名字。
④作用域插槽支持ES6解構
將上述例子中父組件改一下
<template> <div id="app"> <son> <template v-slot:news = "{newsList}"> <ul> <li v-for="(item,index) in newsList" :key="index"> {{index}}、{{item}} </li> </ul> </template> </son> </div> </template>
⑤獨占默認插槽的縮寫語法
當子組件內只有默認插槽時,組件的標簽可以被當作插槽的模板來使用。這樣我們就可以把 v-slot
直接用在組件上
//父組件 <template> <div id="app"> <son v-slot="{news}"> <ul> <li v-for="(item,index) in news" :key="index"> {{item}} </li> </ul> </son> </div> </template> //子組件 <template> <div> <p><slot :news="news"></slot></p> </div> </template>
這里有小坑
1)當子組件內只有默認插槽時,可以省略default,寫作:v-slot = customName
2)當子組件內只有默認插槽時,如果v-slot也准備使用縮寫時(#),default不能被省略,寫作:#default = customName
⑥獨占默認插槽的縮寫語法不能與具名插槽混合使用
//父組件 <template> <div id="app"> <son v-slot="{news}"> <ul> <li v-for="(item,index) in news" :key="index"> {{item}} </li> </ul> <div v-slot:mixinSlot>默認插槽的縮寫語法和具名插槽混用,導致作用域不明確</div> </son> </div> </template> //子組件 <template> <div> <p><slot :news="news"></slot></p> <p><slot name="mixinSlot"></slot></p> </div> </template>
⑦動態插槽名,用來來定義動態的插槽名
在v2.6.0版本中新增動態參數,可以用方括號([])括起來的 JavaScript 表達式作為一個指令的參數,動態參數我將在另一篇文章敘述
//父組件 <template> <div id="app"> <son> <template v-slot:[slotName] ='{ news }'> <ul> <li v-for="(item,index) in news" :key="index">{{item}}</li> </ul> </template> </son> </div> </template> <script> import son from "./components/son"; export default { name: "App", components: { son }, data(){ return{ isOK: false } }, computed: { slotName(){ return this.isOK ? 'slot1' : 'slot2' } }, }; </script> //子組件 <template> <div> <slot name="slot1" :news='news'></slot> <slot name="slot2" :news='news2'></slot> </div> </template> <script> export default { name: "name", data() { return { news: [ "十九屆四中全會28日至31日在京召開", "珍愛和平團結合作 構建人類命運共同體", "法治是最好的營商環境", "夯實優化營商環境的法治基石", "中國營商環境全球排名再前進15名!" ], news2: [ '27省份前三季度GDP出爐 16省份GDP增速跑贏全國', '新航季來了!這些航班將飛大興機場,坐飛機別走錯', '北方回暖南方雨連綿 江南等多地氣溫將創新低', '水潤民心 脫貧路上“領頭雁” 鍾聲', '看看第六屆世界互聯網大會國際組織說了啥' ] }; } }; </script>
印象中,好像沒什么地方需要用到動態插槽名,如果有大大遇到需要使用,還請留言,非常感謝,上述栗子如果用v-if,語義更明朗
⑧v-slot縮寫為:#
具名插槽縮寫為:#name
作用域插槽縮寫
1)當為匿名作用域插槽時:#default = customName(#=customName這種寫法為報錯)
2)當為具名作用域插槽時:#name = customName