做自(zì)由與創造的先行者

透傳 Attributes

Vue.js中文(wén)手冊

此章節假設你(nǐ)已經看(kàn)過了(le)組件基礎。若你(nǐ)還不了(le)解組件是什(shén)麽,請(qǐng)先閱讀該章節。

Attributes 繼承 ​

“透傳 attribute”指的是傳遞給一個組件,卻沒有被該組件聲明(míng)爲 props 或 emits 的 attribute 或者 v-on 事(shì)件監聽器。最常見的例子就是 class、style 和(hé) id。

當一個組件以單個元素爲根作(zuò)渲染時(shí),透傳的 attribute 會(huì)自(zì)動被添加到(dào)根元素上(shàng)。舉例來(lái)說,假如我們有一個 <MyButton> 組件,它的模闆長這(zhè)樣:

template

<!-- <MyButton> 的模闆 -->

<button>click me</button>

一個父組件使用(yòng)了(le)這(zhè)個組件,并且傳入了(le) class:

template

<MyButton class="large" />

最後渲染出的 DOM 結果是:

html

<button class="large">click me</button>

這(zhè)裏,<MyButton> 并沒有将 class 聲明(míng)爲一個它所接受的 prop,所以 class 被視(shì)作(zuò)透傳 attribute,自(zì)動透傳到(dào)了(le) <MyButton> 的根元素上(shàng)。

對(duì) class 和(hé) style 的合并 ​

如果一個子組件的根元素已經有了(le) class 或 style attribute,它會(huì)和(hé)從(cóng)父組件上(shàng)繼承的值合并。如果我們将之前的 <MyButton> 組件的模闆改成這(zhè)樣:

template

<!-- <MyButton> 的模闆 -->

<button class="btn">click me</button>

則最後渲染出的 DOM 結果會(huì)變成:

html

<button class="btn large">click me</button>

v-on 監聽器繼承 ​

同樣的規則也(yě)适用(yòng)于 v-on 事(shì)件監聽器:

template

<MyButton @click="onClick" />

click 監聽器會(huì)被添加到(dào) <MyButton> 的根元素,即那個原生的 <button> 元素之上(shàng)。當原生的 <button> 被點擊,會(huì)觸發父組件的 onClick 方法。同樣的,如果原生 button 元素自(zì)身也(yě)通過 v-on 綁定了(le)一個事(shì)件監聽器,則這(zhè)個監聽器和(hé)從(cóng)父組件繼承的監聽器都會(huì)被觸發。

深層組件繼承 ​

有些(xiē)情況下(xià)一個組件會(huì)在根節點上(shàng)渲染另一個組件。例如,我們重構一下(xià) <MyButton>,讓它在根節點上(shàng)渲染 <BaseButton>:

template

<!-- <MyButton/> 的模闆,隻是渲染另一個組件 -->

<BaseButton />

此時(shí) <MyButton> 接收的透傳 attribute 會(huì)直接繼續傳給 <BaseButton>。

請(qǐng)注意:

透傳的 attribute 不會(huì)包含 <MyButton> 上(shàng)聲明(míng)過的 props 或是針對(duì) emits 聲明(míng)事(shì)件的 v-on 偵聽函數,換句話(huà)說,聲明(míng)過的 props 和(hé)偵聽函數被 <MyButton>“消費”了(le)。

透傳的 attribute 若符合聲明(míng),也(yě)可以作(zuò)爲 props 傳入 <BaseButton>。

禁用(yòng) Attributes 繼承 ​

如果你(nǐ)不想要一個組件自(zì)動地繼承 attribute,你(nǐ)可以在組件選項中設置 inheritAttrs: false。

最常見的需要禁用(yòng) attribute 繼承的場景就是 attribute 需要應用(yòng)在根節點以外(wài)的其他(tā)元素上(shàng)。通過設置 inheritAttrs 選項爲 false,你(nǐ)可以完全控制透傳進來(lái)的 attribute 被如何使用(yòng)。

這(zhè)些(xiē)透傳進來(lái)的 attribute 可以在模闆的表達式中直接用(yòng) $attrs 訪問到(dào)。

template

<span>Fallthrough attribute: {{ $attrs }}</span>

這(zhè)個 $attrs 對(duì)象包含了(le)除組件所聲明(míng)的 props 和(hé) emits 之外(wài)的所有其他(tā) attribute,例如 class,style,v-on 監聽器等等。

有幾點需要注意:

和(hé) props 有所不同,透傳 attributes 在 JavaScript 中保留了(le)它們原始的大(dà)小(xiǎo)寫,所以像 foo-bar 這(zhè)樣的一個 attribute 需要通過 $attrs['foo-bar'] 來(lái)訪問。

像 @click 這(zhè)樣的一個 v-on 事(shì)件監聽器将在此對(duì)象下(xià)被暴露爲一個函數 $attrs.onClick。

現(xiàn)在我們要再次使用(yòng)一下(xià)之前小(xiǎo)節中的 <MyButton> 組件例子。有時(shí)候我們可能(néng)爲了(le)樣式,需要在 <button> 元素外(wài)包裝一層 <div>:

template

<div class="btn-wrapper">

<button class="btn">click me</button>

</div>

我們想要所有像 class 和(hé) v-on 監聽器這(zhè)樣的透傳 attribute 都應用(yòng)在内部的 <button> 上(shàng)而不是外(wài)層的 <div> 上(shàng)。我們可以通過設定 inheritAttrs: false 和(hé)使用(yòng) v-bind="$attrs" 來(lái)實現(xiàn):

template

<div class="btn-wrapper">

<button class="btn" v-bind="$attrs">click me</button>

</div>

小(xiǎo)提示:沒有參數的 v-bind 會(huì)将一個對(duì)象的所有屬性都作(zuò)爲 attribute 應用(yòng)到(dào)目标元素上(shàng)。

多根節點的 Attributes 繼承 ​

和(hé)單根節點組件有所不同,有着多個根節點的組件沒有自(zì)動 attribute 透傳行爲。如果 $attrs 沒有被顯式綁定,将會(huì)抛出一個運行時(shí)警告。

template

<CustomLayout id="custom-layout" @click="changeValue" />

如果 <CustomLayout> 有下(xià)面這(zhè)樣的多根節點模闆,由于 Vue 不知(zhī)道(dào)要将 attribute 透傳到(dào)哪裏,所以會(huì)抛出一個警告。

template

<header>...</header>

<main>...</main>

<footer>...</footer>

如果 $attrs 被顯式綁定,則不會(huì)有警告:

template

<header>...</header>

<main v-bind="$attrs">...</main>

<footer>...</footer>

在 JavaScript 中訪問透傳 Attributes ​

如果需要,你(nǐ)可以通過 $attrs 這(zhè)個實例屬性來(lái)訪問組件的所有透傳 attribute:

js

export default {

created() {

console.log(this.$attrs)

}

}

網站(zhàn)建設開(kāi)發|APP設計(jì)開(kāi)發|小(xiǎo)程序建設開(kāi)發
下(xià)一篇:插槽 Slots
上(shàng)一篇:組件 v-model