做(zuò)自(zì)由與創造的先行(xíng)者

透傳 Attributes

Vue.js中文手冊

此章(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)發
下(xià)一(yī)篇:插槽 Slots
上(shàng)一(yī)篇:組件 v-model