Skip to content

Vue 3 實戰:掌握透傳屬性(Fallthrough Attributes)與 $attrs 的靈活運用

在開發 Vue 元件時,我們常會遇到這種情況:父元件傳入了一些屬性(如 classiddisabled@click),但子元件並沒有透過 definePropsdefineEmits 宣告它們。這些 未被宣告 的屬性就會變成 透傳屬性(Fallthrough Attributes),也就是 attrs

預設情況下,Vue 會自動將這些屬性掛載到子元件的根元素(Root Element)上。

什麼是透傳屬性?

讓我們透過一個實戰範例來區分 props 與 attrs:

上(父)層

html
<MyButton class="primary" id="submit-btn" disabled text="送出" />

下(子)層

js
defineProps({
  text: {
    type: String,
    required: true,
    default: "button",
  },
});

解析結果:

  • text: 因為有在 defineProps 宣告,它是 props
  • classiddisabled: 未被宣告,它們被歸類為 Attributes($attrs,並自動加在子元件的根元素上。。

進階控制:關閉自動透傳

有時候我們不希望 Vue 自動將屬性亂塞到根元素(例如根元素只是一個包裝層),這時可以透過 defineOptions 來關閉這個行為:

js
defineOptions({
  inheritAttrs: false,
});

核心觀念

inheritAttrs 設定為 false 後:

  • 屬性就不會自動加到元件的根元素上。
  • 開發者必須手動決定這些屬性($attrs)要放在哪裡,實現更精準的 UI 控制。

如何手動取得並分配 $attrs

當您關閉自動透傳後,可以透過以下兩種方式取得這些被遺忘的屬性:

在 Template 中直接使用 $attrs

這在想要將屬性轉發給內部特定元素時非常實用:

html
<p>{{ $attrs }}</p>

在 Script 中使用 useAttrs()

如果您需要在邏輯中處理這些屬性,可以使用 Composition API:

vue
<script setup>
import { useAttrs } from "vue";

const attrs = useAttrs();

// 您可以觀察到所有的透傳屬性
console.log(attrs);
console.log(attrs.class);
console.log(attrs.id);
</script>

<template>
  <ThroughIn v-bind="attrs" />
</template>

特殊應用:透過 $attrs 向外傳遞事件

透傳屬性不僅包含資料,也包含 事件監聽器。若要在自定義元件內手動觸發父層傳來的點擊事件,必須注意命名方式(需使用 on 開頭):

html
<input type="button" value="Out 按鈕" @click="$attrs.onClick" />

或是直接使用 v-bind 將所有屬性與事件一次性轉發給內層元件:

html
<InnerComponent v-bind="attrs" />

總結

掌握透傳屬性是封裝高品質 UI 元件(如 Button、Input)的必經之路。透過 inheritAttrs: false$attrs 的配合,您能確保元件的 HTML 結構乾淨,同時保有父元件傳入樣式與事件的靈活性。