Vue插槽slot詳細介紹(對比版本變化,避免踩坑)
Vue中的插槽(slot)在項目中用的也是比較多的,今天就來介紹一下插槽的基本使用以及Vue版本更新之后的插槽用法變化。
插槽是什么?
插槽就是子組件中的提供給父組件使用的一個占位符,用<slot></slot> 表示,父組件可以在這個占位符中填充任何模板代碼,如 HTML、組件等,填充的內(nèi)容會替換子組件的<slot></slot>標簽。簡單理解就是子組件中留下個“坑”,父組件可以使用指定內(nèi)容來補“坑”。以下舉例子幫助理解。
怎么使用插槽?
基本用法
現(xiàn)在,有兩個組件,A與B,分別如下:
A.vue
<template> <div> <p>我是A組件</p> </div> </template> <script> export default { name:'A', data(){ return { } } } </script>
B.vue
<template> <div> <p>我是B組件</p> </div> </template> <script> export default { name:'B', data(){ return { } } } </script>
將B組件引入A組件里面(此時B為A的子組件)
<template> <div> <p>我是A組件</p> <B><B/> </div> </template> <script> import B from './B.vue' //引入B組件 export default { name:'A', components:{ //注冊B組件 B }, data(){ return { } } } </script>
頁面效果如下:
準備工作完畢,現(xiàn)在,在B組件里面使用插槽(slot)
<template> <div> <p>我是B組件</p> <slot></slot> //插槽的使用方式 </div> </template> <script> export default { name:'B', data(){ return { } } } </script>
此時頁面并無變化(最開始的情況),當然,B組件中使用了插槽slot之后,相當于留下了一個“坑”,占了個位置。 那么如何驗證其存在了呢?
此時,修改A組件里面的代碼
<template> <div> <p>我是A組件</p> <B> 驗證插槽是否生效 //用B組件標簽包裹內(nèi)容,驗證slot </B> </div> </template> <script> import B from './B.vue' export default { name:'A', components:{ B }, data(){ return { } } } </script>
此時頁面的效果如下:
頁面中多出了在A中用B包裹的內(nèi)容。沒錯,這就是插槽的基本使用,是不是很簡單?
Vue 實現(xiàn)了一套內(nèi)容分發(fā)的 API,這套 API 的設(shè)計靈感源自 Web Components 規(guī)范草案,將 <slot>
元素作為承載分發(fā)內(nèi)容的出口。
如上面的例子,當組件渲染的時候,<slot></slot>
將會被替換為“驗證插槽是否生效”(即指定內(nèi)容)。插槽內(nèi)可以包含任何模板代碼,包括 HTML:
<template> <div class="main"> <p>我是A組件</p> <B> <span style="color:red">驗證插槽是否生效</span> //內(nèi)容為html </B> </div> </template>
頁面效果如下:
插槽內(nèi)也可以放其他組件,如此時再新建一個組件C:
<template> <div> <p>我是C組件</p> </div> </template> <script> export default { name:'C', data(){ return { } } } </script>
在A組件中,將B組件包裹的內(nèi)容換成C組件:
<template> <div class="main"> <p>我是A組件</p> <B> <!-- <span style="color:red">驗證插槽是否生效</span> --> <C /> //插入C組件 </B> </div> </template> <script> import B from './B.vue' import C from './C.vue' //引入C組件 export default { name:'A', components:{ B, C //注冊C組件 }, data(){ return { } } } </script>
頁面效果如下:
此時檢查頁面元素,我們會發(fā)現(xiàn),在原本B組件中<slot></slot>的位置,替換成了C組件:
//B.vue <template> <div> <p>我是B組件</p> <slot></slot> </div> </template> //觀察頁面元素,<slot></slot>被替換成C組件
也印證了開篇對插槽作用的解釋,即使用<slot></slot>的組件指定的位置留一個坑,如果在外部,使用其組件包裹某內(nèi)容(可以是任何模板代碼,也可以是HTML,還可以是組件),則該內(nèi)容就會被分發(fā)到<slot></slot>處(一個有趣的說法就是把“坑”補上),渲染出來。當然,也可以不放任何內(nèi)容,不影響組件渲染,就好比最開始的情況。
注意:如果B組件的 template
中沒有包含一個 <slot>
元素,即不使用插槽,則該組件起始標簽和結(jié)束標簽之間的任何內(nèi)容都會被拋棄。例如:
//B.vue <template> <div> <p>我是B組件</p> <!-- <slot></slot> --> //不使用插槽 </div> </template>
//A.vue <template> <div> <p>我是A組件</p> <B> <!-- <span style="color:red">驗證插槽是否生效</span> --> <C /> </B> </div> </template> //此時在<B></B>包裹的內(nèi)容都會被拋棄
頁面效果如下,在B組件中插入的C組件被拋棄了,因為B組件中沒使用插槽:
后備(默認)內(nèi)容
有時為一個插槽設(shè)置具體的后備 (也就是默認的) 內(nèi)容是很有用的,它只會在沒有提供內(nèi)容的時候被渲染。例如在B組件中:
<template> <div> <slot></slot> </div> </template>
我們可能希望這個B組件內(nèi)絕大多數(shù)情況下都渲染文本“我是B組件”。為了將“我是B組件”作為后備內(nèi)容,我們可以將它放在 <slot>
標簽內(nèi):
<template> <div> <slot><p>我是B組件</p></slot> </div> </template>
現(xiàn)在當我在一個父級組件中使用B組件并且不提供任何插槽內(nèi)容時:
<B></B>
后備內(nèi)容“我是B組件”將會被渲染:
但是如果我們提供內(nèi)容:
<B> <p>我是插槽內(nèi)容</p> </B>
則這個提供的內(nèi)容將會被渲染從而取代后備內(nèi)容:
具名插槽
所謂具名插槽,顧名思義就是起了名字的插槽。有時我們需要多個插槽,例如當我們想使用某種通用模板:
<template> <div> <header> <!-- 我們希望把頁頭放這里 --> </header> <main> <!-- 我們希望把主要內(nèi)容放這里 --> </main> <footer> <!-- 我們希望把頁腳放這里 --> </footer> </div> </template>
對于這樣的情況,<slot>
元素有一個特殊的 attribute:name
。這個 attribute 可以用來定義額外的插槽:
//B.vue <template> <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template>
一個不帶 name
的 <slot>
出口會帶有隱含的名字“default”。
在向具名插槽提供內(nèi)容的時候,我們可以在一個 <template>
元素上使用 slot
指令,并以 slot
的參數(shù)的形式提供其名稱(當然也可以直接放在標簽中,如<div slot="header">):
<template> <div> <p>我是A組件</p> <B> <template slot="header"> <p>我是header部分</p> </template> <p>我是main(默認插槽)部分</p> <template slot="footer"> <p>我是footer部分</p> </template> </B> </div> </template>
現(xiàn)在 <template>
元素中的所有內(nèi)容都將會被傳入相應(yīng)的插槽。任何沒有被包裹在帶有slot
的 <template>
中的內(nèi)容都會被視為默認插槽的內(nèi)容。
頁面效果如下:
觀察頁面元素,內(nèi)容被放入相應(yīng)名字的插槽中:
Tips:說到這里就不得不提一下,這種方式在項目中比較常用,可以當成一個復(fù)用(通用)模板組件。如多個組件的布局使用相似模板,只是具體內(nèi)容不同,那么我們可以使用這種插槽方式封裝成一個通用組件,在其他組件使用的時候只需要傳對應(yīng)的內(nèi)容到對應(yīng)名字的插槽即可,不需要將該模板在每個組件重新寫一遍,減少代碼冗余,大大提高開發(fā)效率。
作用域插槽
有時讓插槽內(nèi)容能夠訪問子組件中才有的數(shù)據(jù)是很有用的?,F(xiàn)在,假設(shè)B組件:
<template> <div> <p>我是B組件</p> <slot>{{obj.firstName}}</slot> </div> </template> <script> export default { name:'B', data(){ return { obj:{ firstName:'leo', lastName:'lion' } } } } </script>
我們可能想換掉備用內(nèi)容,用“lion”來顯示。如下,在A組件:
<template> <div> <p>我是A組件</p> <B> {{obj.lastName}} </B> </div> </template>
然而上述代碼不會正常工作,因為只有B組件可以訪問到 obj,而我們提供的內(nèi)容是在父級渲染的,即在父級作用域中。頁面并無變化:
為了讓 obj在父級的插槽內(nèi)容中可用,我們可以將 obj作為 <slot>
元素的一個 attribute 綁定上去:
<template> <div> <p>我是B組件</p> <slot :obj="obj">{{obj.firstName}}</slot> </div> </template>
綁定在 <slot>
元素上的 attribute 被稱為插槽 prop。現(xiàn)在在父級作用域中,我們可以使用帶值的 slot-scope
來定義我們提供的插槽 prop 的名字:
<template> <div class="main"> <p>我是A組件</p> <B> <template slot-scope="data"> {{data.obj.lastName}} </template> </B> </div> </template>
在這個例子中,我們選擇將包含所有插槽 prop 的對象命名為 data,但你也可以使用任意你喜歡的名字。此時頁面效果如下:
如果你有使用過ElementUI里面的表格el-table,當改變某一列展示的字段時,我們經(jīng)常使用:
<el-table-column> <template slot-scope="scope"> <span>{{scope.row.xxx}}</span> </template> </el-table-column>
插槽版本變化
v-slot
指令自 Vue 2.6.0 起被引入,提供更好的支持 slot
和 slot-scope
attribute 的 API 替代方案。v-slot
完整的由來參見這份 RFC。在接下來所有的 2.x 版本中 slot
和 slot-scope
attribute 仍會被支持,但已經(jīng)被官方廢棄且不會出現(xiàn)在 Vue 3 中。也就是說,在vue2版本中,我們?nèi)钥梢允褂胹lot跟slot-scope,但是在vue3中就只能使用v-slot了。
原來的帶有slot的具名插槽
//B.vue <template> <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> </template>
寫法變化,使用v-slot
<template> <div> <p>我是A組件</p> <B> <template v-slot:header> <p>我是header部分</p> </template> <p>我是main(默認插槽)部分</p> <template v-slot:footer> <p>我是footer部分</p> </template> </B> </div> </template>
原來的作用域插槽
<template> <div class="main"> <p>我是A組件</p> <B> <template slot-scope="data"> {{data.obj.lastName}} </template> </B> </div> </template>
寫法變化,使用v-slot
<template> <div class="main"> <p>我是A組件</p> <B> <template v-slot="data"> {{data.obj.lastName}} </template> </B> </div> </template>
在 2.6.0 中,為具名插槽和作用域插槽引入了一個新的統(tǒng)一的語法 (即 v-slot
指令)。它取代了 slot
和 slot-scope
這兩個目前已被廢棄但未被移除且仍在文檔中的 attribute。新語法的由來可查閱這份 RFC。注意slot版本變化,vue2中仍可以使用slot與slot-scope,但是vue3只能使用v-slot了,切記,避免踩坑。
總結(jié)
到此這篇關(guān)于Vue插槽slot詳細介紹的文章就介紹到這了,更多相關(guān)Vue插槽slot介紹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue mixins組件復(fù)用的幾種方式(小結(jié))
這篇文章主要介紹了vue mixins組件復(fù)用的幾種方式(小結(jié)),vue中提供了一種混合機制mixins,用來更高效的實現(xiàn)組件內(nèi)容的復(fù)用,有興趣的可以了解一下2017-09-09Vue3?$emit用法指南(含選項API、組合API及?setup?語法糖)
這篇文章主要介紹了Vue3?$emit用法指南,使用?emit,我們可以觸發(fā)事件并將數(shù)據(jù)傳遞到組件的層次結(jié)構(gòu)中,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2022-07-07