此章(zhāng)節假設你已經看(kàn)過了(le)組件基礎。若你還不了(le)解組件是什麽,請(qǐng)先閱讀該章(zhāng)節。
Attributes 繼承
“透傳 attribute”指的是傳遞給一(yī)個組件,卻沒有被該組件聲明(míng)為(wèi) props 或 emits 的 attribute 或者 v-on 事件監聽器。最常見(jiàn)的例子就是 class、style 和(hé) id。
當一(yī)個組件以單個元素為(wèi)根作(zuò)渲染時(shí),透傳的 attribute 會自(zì)動被添加到根元素上(shàng)。舉例來說,假如(rú)我們有一(yī)個 <MyButton> 組件,它的模闆長(cháng)這(zhè)樣:
template
<!-- <MyButton> 的模闆 -->
<button>click me</button>
一(yī)個父組件使用了(le)這(zhè)個組件,并且傳入了(le) class:
template
<MyButton class="large" />
最後渲染出的 DOM 結果是:
html
<button class="large">click me</button>
這(zhè)裏,<MyButton> 并沒有将 class 聲明(míng)為(wèi)一(yī)個它所接受的 prop,所以 class 被視(shì)作(zuò)透傳 attribute,自(zì)動透傳到了(le) <MyButton> 的根元素上(shàng)。
對 class 和(hé) style 的合并
如(rú)果一(yī)個子組件的根元素已經有了(le) class 或 style attribute,它會和(hé)從(cóng)父組件上(shàng)繼承的值合并。如(rú)果我們将之前的 <MyButton> 組件的模闆改成這(zhè)樣:
template
<!-- <MyButton> 的模闆 -->
<button class="btn">click me</button>
則最後渲染出的 DOM 結果會變成:
html
<button class="btn large">click me</button>
v-on 監聽器繼承
同樣的規則也适用于 v-on 事件監聽器:
template
<MyButton @click="onClick" />
click 監聽器會被添加到 <MyButton> 的根元素,即那(nà)個原生的 <button> 元素之上(shàng)。當原生的 <button> 被點擊,會觸發父組件的 onClick 方法。同樣的,如(rú)果原生 button 元素自(zì)身也通(tōng)過 v-on 綁定了(le)一(yī)個事件監聽器,則這(zhè)個監聽器和(hé)從(cóng)父組件繼承的監聽器都(dōu)會被觸發。
深層組件繼承
有些情況下(xià)一(yī)個組件會在根節點上(shàng)渲染另一(yī)個組件。例如(rú),我們重構一(yī)下(xià) <MyButton>,讓它在根節點上(shàng)渲染 <BaseButton>:
template
<!-- <MyButton/> 的模闆,隻是渲染另一(yī)個組件 -->
<BaseButton />
此時(shí) <MyButton> 接收的透傳 attribute 會直接繼續傳給 <BaseButton>。
請(qǐng)注意:
透傳的 attribute 不會包含 <MyButton> 上(shàng)聲明(míng)過的 props 或是針對 emits 聲明(míng)事件的 v-on 偵聽函數(shù),換句話說,聲明(míng)過的 props 和(hé)偵聽函數(shù)被 <MyButton>“消費(fèi)”了(le)。
透傳的 attribute 若符合聲明(míng),也可(kě)以作(zuò)為(wèi) props 傳入 <BaseButton>。
禁用 Attributes 繼承
如(rú)果你不想要(yào)一(yī)個組件自(zì)動地(dì)繼承 attribute,你可(kě)以在組件選項中設置 inheritAttrs: false。
最常見(jiàn)的需要(yào)禁用 attribute 繼承的場景就是 attribute 需要(yào)應用在根節點以外(wài)的其他(tā)元素上(shàng)。通(tōng)過設置 inheritAttrs 選項為(wèi) false,你可(kě)以完全控制透傳進來的 attribute 被如(rú)何使用。
這(zhè)些透傳進來的 attribute 可(kě)以在模闆的表達式中直接用 $attrs 訪問(wèn)到。
template
<span>Fallthrough attribute: {{ $attrs }}</span>
這(zhè)個 $attrs 對象包含了(le)除組件所聲明(míng)的 props 和(hé) emits 之外(wài)的所有其他(tā) attribute,例如(rú) class,style,v-on 監聽器等等。
有幾點需要(yào)注意:
和(hé) props 有所不同,透傳 attributes 在 JavaScript 中保留了(le)它們原始的大小寫,所以像 foo-bar 這(zhè)樣的一(yī)個 attribute 需要(yào)通(tōng)過 $attrs['foo-bar'] 來訪問(wèn)。
像 @click 這(zhè)樣的一(yī)個 v-on 事件監聽器将在此對象下(xià)被暴露為(wèi)一(yī)個函數(shù) $attrs.onClick。
現在我們要(yào)再次使用一(yī)下(xià)之前小節中的 <MyButton> 組件例子。有時(shí)候我們可(kě)能(néng)為(wèi)了(le)樣式,需要(yào)在 <button> 元素外(wài)包裝一(yī)層 <div>:
template
<div class="btn-wrapper">
<button class="btn">click me</button>
</div>
我們想要(yào)所有像 class 和(hé) v-on 監聽器這(zhè)樣的透傳 attribute 都(dōu)應用在內(nèi)部的 <button> 上(shàng)而不是外(wài)層的 <div> 上(shàng)。我們可(kě)以通(tōng)過設定 inheritAttrs: false 和(hé)使用 v-bind="$attrs" 來實現:
template
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">click me</button>
</div>
小提示:沒有參數(shù)的 v-bind 會将一(yī)個對象的所有屬性都(dōu)作(zuò)為(wèi) attribute 應用到目标元素上(shàng)。
多根節點的 Attributes 繼承
和(hé)單根節點組件有所不同,有着多個根節點的組件沒有自(zì)動 attribute 透傳行(xíng)為(wèi)。如(rú)果 $attrs 沒有被顯式綁定,将會抛出一(yī)個運行(xíng)時(shí)警告。
template
<CustomLayout id="custom-layout" @click="changeValue" />
如(rú)果 <CustomLayout> 有下(xià)面這(zhè)樣的多根節點模闆,由于 Vue 不知道(dào)要(yào)将 attribute 透傳到哪裏,所以會抛出一(yī)個警告。
template
<header>...</header>
<main>...</main>
<footer>...</footer>
如(rú)果 $attrs 被顯式綁定,則不會有警告:
template
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
在 JavaScript 中訪問(wèn)透傳 Attributes
如(rú)果需要(yào),你可(kě)以通(tōng)過 $attrs 這(zhè)個實例屬性來訪問(wèn)組件的所有透傳 attribute:
js
export default {
created() {
console.log(this.$attrs)
}
}
網站建設開(kāi)發|APP設計開(kāi)發|小程序建設開(kāi)發