“透明屬性”是指傳遞給組件但未聲明為props 或由組件發(fā)出的屬性或v-on 事件偵聽器。最常見的例子是class、style 和id。
當以單個元素為根渲染組件時,透明屬性將自動添加到根元素。例如,如果我們有一個MyButton 組件,它的模板如下所示:
(資料圖片僅供參考)
!-- MyButton 的模板--buttonclick me/button 父組件使用該組件并傳入類:
MyButton class='large' /最終渲染的DOM結果為:
button class='large'click me/button 這里,MyButton 沒有將class 聲明為它接受的prop,因此class 被視為傳遞屬性,并自動傳遞到MyButton 的根元素。
如果您不希望組件自動繼承屬性,可以在組件選項中將inheritAttrs: 設置為false。
需要禁用屬性繼承的最常見場景是當屬性需要應用于除根節(jié)點之外的其他元素時。通過將繼承屬性選項設置為false,您可以完全控制傳入屬性的使用方式。
這些透明傳遞的屬性可以在模板表達式中使用$attrs 直接訪問。
spanFallthrough attribute: {{ $attrs }}/span $attrs 對象包含除組件聲明的props 和Emits 之外的所有其他屬性,例如類、樣式、v-on 偵聽器等。
有幾點需要注意:
與props 不同,傳遞屬性在JavaScript 中保留其原始大小寫,因此像foo-bar 這樣的屬性需要通過$attrs['foo-bar'] 訪問。像@click 這樣的v-on 事件監(jiān)聽器將作為該對象下的函數(shù)$attrs.onClick 公開。
我們已經了解到組件可以接收任何類型的JavaScript 值作為props,但是組件如何接收模板內容呢?在某些場景下,我們可能希望將一些模板片段傳遞給子組件,并讓子組件在其組件中渲染這些片段。
例子:
模板h1{{ title }}/h1 BaseSlot div h3 標題:/h3 p 內容:/p /div /BaseSlot/templatescriptimport BaseSlot from './components/BaseSlot.vue'; export default { data() { return { title: ' slot' } }, Components: { BaseSlot }}/scripttemplate h2{{ title }}/h2 !-- Slot 導出-- slot/slot/templatescriptexport default { data() { return { title:'Slot information' } }} /scriptslot 元素是一個插槽出口,指示父元素提供的插槽內容將在何處呈現(xiàn)。
槽內容可以訪問父組件的數(shù)據(jù)范圍,因為槽內容本身是在父組件模板中定義的。
模板h1{{ title }}/h1 ComponentA p{{ message }}/p /ComponentA/templatescriptimport ComponentA from './components/ComponentA.vue';export default { data() { return { title: 'slots', message:' App-ComponentA-message' } }, Components: { ComponentA }}/scripttemplate h2{{ title }}/h2 p {{ message }}/p slot/slot/templatescriptexport 默認{ data() { return { title: 'A ', message: 'Component A - message' } }, Components: { }}/script 這里的兩個{{ message }} 插值表達式呈現(xiàn)相同的內容。
槽內容無法訪問子組件的數(shù)據(jù)。 Vue 模板中的表達式只能訪問它們定義的作用域,這與JavaScript 的詞法作用域規(guī)則一致。換句話說:
當沒有外部提供內容時,可以為插槽指定默認內容。
如果我們想使用父組件而不提供任何槽位內容,只需要在槽位標簽之間寫入默認內容作為默認內容即可。
template h1{{ title }}/h1 ComponentA !-- p{{ message }}/p -- /ComponentA/templatescriptimport ComponentA from './components/ComponentA.vue';export default { data() { return { title: ' slot slot', message:'App-ComponentA-message' } }, Components: { ComponentA }}/scripttemplate h2{{ title }}/h2 p {{ message }}/p slot 默認內容/slot/templatescriptexport 默認{ data( ) { return { title: 'A', message: 'Component A - message' } }, Components: { }}/script
有時,在組件中擁有多個插槽出口很有用。
要傳遞命名槽的內容,我們需要使用帶有v-slot 指令的模板元素,并將目標槽的名稱傳遞給該指令:
template h2{{ title }}/h2 slot name='top'default content/slot br slot name='content'default content/slot/templateslot 元素可以有一個特殊的屬性名稱,用于為每個元素分配唯一的屬性投幣口。 ID來確定每個位置要渲染的內容
ComponentA template v-slot:top p{{ slotTopMsg }}/p /template template v-slot:content p{{ slotContentMsg }}/p /template /ComponentAv-slot 有對應的簡寫#,所以template v-slot:top 可以簡寫為template #頂部。它的意思是“將模板片段的這一部分傳遞到子組件的頂部插槽中”*。
完整示例:
template h1{{ title }}/h1 ComponentA template #top p{{ slotTopMsg }}/p /template template v-slot:content p{{ slotContentMsg }}/p /template /ComponentA/templatescriptimport ComponentA from './components/ComponentA. vue';export default { data() { return { title: 'slots', slotTopMsg:'slot top msg', slotContentMsg:'slot content msg' } }, Components: { ComponentA }}/scripttemplate h2{{ title }}/h2 插槽名稱='top'default content/slot br slot name='content'default content/slot/templatescriptexport default { data() { return { title: 'A' } }, Components: { }}/script
slot 內容無法訪問子組件的狀態(tài)。
然而,在某些情況下,槽的內容可能想要使用來自父組件域和子組件域的數(shù)據(jù)。
為此,我們需要一種方法讓子組件在渲染時向插槽提供其部分數(shù)據(jù)。
您可以將屬性傳遞到插槽的出口,就像將props 傳遞到組件一樣。
template h3{{ title }}/h3 slot :text='childMessage' :count='1'/slot/template 當您需要接收slot props 時,默認slot 和命名slot 的使用方式存在一些細微的差異。下面我們首先展示默認槽是如何接受props 的。通過子組件標簽上的v-slot 指令,直接接收到一個slot props 對象:
ComponentB v-slot='slotProps' h2{{ message }}/h2 ptext: {{ slotProps.text }}/p pcount: {{ slotProps.count }}/p /ComponentB
命名范圍插槽的工作方式相同類似, slot props 可以作為v-slot 指令的值來訪問:v-slot:name='slotProps'。使用縮寫時:
ComponentB h2{{ message }}/h2 template #one='slotProps' pone - text: {{ slotProps.text }}/p /template template #two='slotProps' ptwo - count: {{ slotProps.count }}/p/template /ComponentB 將props 傳遞到指定的槽中:
template h3{{ title }}/h3 hr !-- slot :text='childMessage' :count='1'/slot -- slot name='one' :text='childMessage'/slot hr slot name='two' :count='1'/slot/template 完整示例:
模板h1{{ title }}/h1 !-- ComponentB v-slot='slotProps' h2{{ message }}/h2 ptext: {{ slotProps.text }}/p pcount: {{ slotProps.count }}/p /ComponentB -- ComponentB h2{{ message }}/h2 template #one='slotProps' pone - text: {{ slotProps.text }}/p /template template #two='slotProps' ptwo - count: {{ slotProps.count }}/p /template /ComponentB/templatescriptimport ComponentB from './components/ComponentB.vue';export default { data() { return { title: 'slots', message: 'App-parent' } }, Components: { //ComponentA , ComponentB } }/scripttemplate h3{{ title }}/h3 hr !-- 插槽:text='childMessage' :count='1'/slot -- 插槽名稱='one' :text='childMessage'/slot hr 插槽名稱='two' :count='1'/slot/templatescriptexport default { data() { return { title: '組件b', childMessage: '組件B的數(shù)據(jù)' } }}/script