Vue
fallthrough attritube 指的是傳遞給元件的屬性或是 v-on 事件監聽器,但卻沒有透過 props 或 emit 做宣告,常見的例子有 style
、class
、id
的屬性
舉個例子,假設有個 MyButton 元件的模板如下
<button>click me</button>
另一個元件使用了這個 button 元件,並傳入 class=large
的屬性
<MyButton class="large" />
最後渲染出的 DOM
<button class="large">click me</button>
子元件不需要宣告 class 屬性也能使用父元件定義的 class=large
,這裡的 class
就稱為 fallthrough attribute
class
與 style
的合併如果子元件本來就有 class 屬性
<button class="btn">click me</button>
最後渲染出的 DOM
<button class="btn large">click me</button>
可以看見 class 屬性會合併,同樣的 style 也會自動合併
v-on
監聽器繼承v-on
監聽器也遵循著相同規則
父元件傳入 v-on
<MyButton @click="onClick" />
子元件不用做任何宣告,按下按鈕時也會觸發 onClick 函式
如果子元件本來就有寫 @click="handler",那麼按下時會同時觸發兩個 handler
如果 MyButton 元件的模板也是使用別的元件
<BaseButton/>
通過使用 MyButton 的父元件傳遞過來的 fallthrough 屬性,同樣也會傳給 BaseButton 元件
你如果不想讓元件繼承到父層的屬性,可以把 inheritAttrs
設定成 false
如果你使用 <script setup>
來撰寫,要另外寫一個 <script>
來設定
<script></script>
<script setup>
// ...setup logic
</script>
一般來說會禁用屬性繼承的情況會發生在屬性需要應用在根節點以外的其他元素上,透過禁用 inheritAttrs 你可以完全自由的操控傳進來的屬性。
fallthrough 屬性可以直接透過 $attrs
在模板中做操作
<span>Fallthrough attributes: {{ $attrs }}</span>
foo-bar
,那他就必須透過 $attrs['foo-bar']
來存取,不能使用 $attrs['fooBar']
v-on
事件監聽器(例如 @click) 會轉成一個函式( $attrs.onClick )有時候為了撰寫樣式我們會在原本的元素外再多包一層 div
<div class="btn-wrapper">
<button class="btn">click me</button>
</div>
但我們可能不希望透傳進來的參數套用到外層 div,此時可以透過 v-bind 來實現:
<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">click me</button>
</div>
v-bind
如果沒有綁到指定的參數(ex: id),預設會綁所有屬性到目標元素上
不像單個根節點,多個根節點的元件不會自動做參數透傳,如果沒有特別寫 v-bind 來綁定 $attrs 會產生 warning
有需要的話可以透過在 script setup
中使用 useAttrs()
來傳遞
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
在 SFC 以外的地方可以寫成
export default {
setup(props, ctx) {
// fallthrough attributes are exposed as ctx.attrs
console.log(ctx.attrs)
}
}
attrs 物件只會反應出當下最新的屬性,他並沒有響應性,所以你不能夠使用 watchers 來監控他的改變,如果你需要的是響應性請改用 props,又或者使用 onUpdated()
來操作每次更新後的改變