EP25 - 降級屬性

閱讀時間約 1 分鐘
Fallthrough Attributes 感覺是一種特殊的屬性!
之前文章有提到過幾次了~要好好再研究清楚!
只是這屬性的英文應該是~fall throught 降級的意思?!!! 不是失敗的意思~

這個頁面假設您已經閱讀過「組件基礎」內容。對組件不熟悉,建議先閱讀該部分。

屬性繼承 - Attribute Inheritance

「降級屬性」是指傳遞給組件的屬性或 v-on 事件監聽器,但在接收組件的 props 或 emits 中沒有明確聲明。常見的例子包括 class、style 和 id 屬性。

當組件渲染一個單根元素時,降級屬性將自動添加到根元素的屬性中。例如,給定一個具有以下模板的 <MyButton> 組件:

<!-- <MyButton> 的模板 -->
<button>Click Me</button>

以及一個使用此組件的父組件:

<MyButton class="large" />

最終渲染的 DOM 將是:

<button class="large">Click Me</button>

在這裡,<MyButton> 沒有將 class 聲明為可接受的 prop。因此,class 被視為一個降級屬性,自動添加到 <MyButton> 的根元素中。

class 和 style 的合併 -class and style Merging

如果子組件的根元素已經有現有的 class 或 style 屬性,這些屬性將與從父組件繼承的 class 和 style 值合併。假設我們將前一個例子中 <MyButton> 的模板更改為:

<!-- <MyButton> 的模板 -->
<button class="btn">Click Me</button>

那麼最終渲染的 DOM 將變為:

<button class="btn large">Click Me</button>

v-on 監聽器繼承 - v-on Listener Inheritance

相同的規則適用於 v-on 事件監聽器:

<MyButton @click="onClick" />

click 監聽器將被添加到 <MyButton> 的根元素,即原生 <button> 元素上。當原生 <button> 被點擊時,將觸發父組件的 onClick 方法。如果原生 <button> 已經綁定了一個使用 v-on 的 click 監聽器,那麼兩個監聽器都會被觸發。

嵌套組件繼承 - Nested Component Inheritance

如果一個組件渲染另一個組件作為其根節點,例如,我們重構了 <MyButton> 以渲染 <BaseButton> 作為其根:

<!-- 渲染另一個組件的 <MyButton/> 的模板 -->
<BaseButton />

那麼 <MyButton> 接收到的降級屬性將自動轉發給 <BaseButton>

注意:

  • 被轉發的屬性不包括被聲明為 props 的任何屬性,或由 <MyButton> 聲明的事件的 v-on 監聽器——換句話說,聲明的 props 和監聽器已被 <MyButton>「消耗」。
  • 被轉發的屬性如果被 <BaseButton> 聲明,則可以作為 props 接受。

禁用屬性繼承 - Disabling Attribute Inheritance

如果您不希望組件自動繼承屬性,可以在組件選項中設置 inheritAttrs: false

自 3.3 版本以來,您也可以在 <script setup> 中直接使用 defineOptions

<script setup>
defineOptions({
inheritAttrs: false
})
// ...setup 邏輯
</script>

禁用屬性繼承的常見情境是當屬性需要應用於根節點之外的其他元素時。通過將 inheritAttrs 選項設置為 false,您可以完全控制降級屬性應該應用的位置。

這些降級屬性可以通過 $attrs 在模板表達式中直接訪問:

<span>降級屬性: {{ $attrs }}</span>

$attrs 對象包括所有未由組件的 props 或 emits 選項聲明的屬性(例如 class、style、v-on 監聽器等)。

一些注意事項:

  • 與 props 不同,降級屬性在 JavaScript 中保留其原始大小寫,因此像 foo-bar 這樣的屬性需要作為 $attrs['foo-bar'] 訪問。
  • @click 這樣的 v-on 事件監聽器將作為一個函數暴露在 $attrs 下。

使用我們在前一部分的 <MyButton> 組件示例——有時我們可能需要為樣式目的將實際的 <button> 元素包裹在額外的 <div> 中:

<div class="btn-wrapper">
<button class="btn">Click Me</button>
</div>

我們希望所有降級屬性(如 class 和 v-on 監聽器)應用於內部的 <button>,而不是外部的 <div>。我們可以通過設置 inheritAttrs: falsev-bind="$attrs" 來實現:

<div class="btn-wrapper">
<button class="btn" v-bind="$attrs">Click Me</button>
</div>

請記住,沒有參數v-bind 將對象的所有屬性綁定為目標元素的屬性。

多根節點上的屬性繼承 - Attribute Inheritance on Multiple Root Nodes

與單根節點的組件不同,具有多根節點的組件沒有自動的屬性降級行為。如果 $attrs 沒有明確綁定,將會發出運行時警告。

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

如果 <CustomLayout> 有以下多根模板,將會發出警告,因為 Vue 無法確定將降級屬性應用到哪裡:

<header>...</header>
<main>...</main>
<footer>...</footer>

如果明確綁定了 $attrs,則警告將被抑制:

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

在 JavaScript 中訪問降級屬性 - Accessing Fallthrough Attributes in JavaScript

如果需要,您可以使用 useAttrs() API 在 <script setup> 中訪問組件的降級屬性:

<script setup>
import { useAttrs } from 'vue'

const attrs = useAttrs()
</script>

如果不使用 <script setup>,則 attrs 將作為 setup() 上下文的屬性暴露:

export default {
setup(props, ctx) {
// 降級屬性作為 ctx.attrs 暴露
console.log(ctx.attrs)
}
}

注意,雖然這裡的 attrs 對象始終反映最新的降級屬性,但它不是響應式的(出於性能考慮)。您無法使用監視器來觀察其變化。如果您需要響應性,請使用 prop。或者,您可以使用 onUpdated() 在每次更新時執行副作用。

為什麼看官方文件總有一種不知道他在幹嘛的感覺?
因為繼承放在屬性裡頭真的要多花一點時間理解~
組件之間屬性的關係蠻微妙的~
avatar-img
2會員
70內容數
分享生活趣事~
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
卡關的人生 的其他內容
從 3.4 開始,推薦使用 defineModel() 巨集來自動化這個過程,讓寫法更加簡潔,支持多個 v-model 綁定,並可直接使用自定義修飾符。新方法還能同步父子組件的值,減少同步問題,使組件的開發與維護變得更方便
子組件可以使用 $emit 方法來發送自定義事件,父組件則使用 v-on 來監聽這些事件。事件參數可以通過 $emit 傳遞,並在父組件中使用內聯箭頭函數或方法接收。使用 defineEmits 可以顯式宣告事件並進行驗證,提升代碼可讀性和可維護性。
props的值可以是字符串數組或物件語法,每個屬性的鍵是prop的名字,值是預期類型的建構函數。當解構props時,Vue會自動添加props.前綴以保持響應性。Prop驗證確保了數據類型和要求的一致性,使開發更嚴謹。
接下來要深入探討組件註冊的內容!Vue 組件需要註冊,讓 Vue 知道在模板中遇到組件時在哪裡找到實現。註冊方式有全局和局部兩種。全局註冊適用於通用、頻繁使用的組件,例如按鈕、模態框等;而局部註冊適用於特定頁面或功能,能明確依賴關係,提升維護性。回顧之前的範例,我們都是使用局部註冊呢!
Ex6SimpleComponent.vue 使用 ref 來創建響應式變數 groceryList,並引入 TodoItem 子組件。模板部分使用 <ol> 標籤來創建有序列表,並透過 v-for 指令遍歷 groceryList 陣列,每個項目對應一個 TodoItem 組件。
在這個範例中,我們展示了如何使用 Vue 的 v-model 來實現各種表單元件的雙向綁定。範例包括文字輸入框、單選框、多選框、單選按鈕、下拉選單和多選下拉選單。使用 ref 創建響應式變數,並在 template 中使用 v-model 進行雙向綁定。這使得表單元件能夠即時反映和更新數據。
從 3.4 開始,推薦使用 defineModel() 巨集來自動化這個過程,讓寫法更加簡潔,支持多個 v-model 綁定,並可直接使用自定義修飾符。新方法還能同步父子組件的值,減少同步問題,使組件的開發與維護變得更方便
子組件可以使用 $emit 方法來發送自定義事件,父組件則使用 v-on 來監聽這些事件。事件參數可以通過 $emit 傳遞,並在父組件中使用內聯箭頭函數或方法接收。使用 defineEmits 可以顯式宣告事件並進行驗證,提升代碼可讀性和可維護性。
props的值可以是字符串數組或物件語法,每個屬性的鍵是prop的名字,值是預期類型的建構函數。當解構props時,Vue會自動添加props.前綴以保持響應性。Prop驗證確保了數據類型和要求的一致性,使開發更嚴謹。
接下來要深入探討組件註冊的內容!Vue 組件需要註冊,讓 Vue 知道在模板中遇到組件時在哪裡找到實現。註冊方式有全局和局部兩種。全局註冊適用於通用、頻繁使用的組件,例如按鈕、模態框等;而局部註冊適用於特定頁面或功能,能明確依賴關係,提升維護性。回顧之前的範例,我們都是使用局部註冊呢!
Ex6SimpleComponent.vue 使用 ref 來創建響應式變數 groceryList,並引入 TodoItem 子組件。模板部分使用 <ol> 標籤來創建有序列表,並透過 v-for 指令遍歷 groceryList 陣列,每個項目對應一個 TodoItem 組件。
在這個範例中,我們展示了如何使用 Vue 的 v-model 來實現各種表單元件的雙向綁定。範例包括文字輸入框、單選框、多選框、單選按鈕、下拉選單和多選下拉選單。使用 ref 創建響應式變數,並在 template 中使用 v-model 進行雙向綁定。這使得表單元件能夠即時反映和更新數據。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
上一篇文章提到有些介面不應被繼承,但物件導向的子類別只能繼承父類別的介面,因而產生一些不合適的介面實作。trait/typeclass則沒有這種繼承機制,這似乎使需要繼承的特性無法直接使用。然而函數式導向比起繼承,更適合使用組合,根本不需要使用繼承疊加特性。 資料類型的定義往往跟怎麼建構模型相
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
各位使用 Vue.js 開發的小夥伴們,你們都怎麼實作父子層組件資料的雙向綁定呢?如果你還在寫 prop + emit 的話,不妨進來看看吧。
Thumbnail
切換頁面卡卡有很多種原因,這裡舉的例子只針對元件太大的情境。 除了想辦法拆分外,還有一個方法就是利用 Vue 的 Async Component。
Thumbnail
一開始你先把你的專案push上去後,修改vite.config.ts ,要在裡面新增  base: "/Cart/" (/放自己的專案名稱/) build: {outDir: "docs"}, 接下來你要去你的github setting 裡面 -> Page ->選Deploy fro
Thumbnail
前言 從零開始構建一個 DateTimePicker 可能看起來令人畏懼,但試想一下你將獲得的靈活性和控制力。在這個系列中,我們將逐步揭開構建過程的神秘面紗,讓您能夠創建一個完全符合需求的自定義 DateTimePicker。 本文章,屬於付費系列的文章,這篇文章,我會希望讀者可以得到的
Thumbnail
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。 此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找
Thumbnail
我們在實作中,難免會遇到在不同組件中,卻有需求相同的資料格式,因此 mixins 可以達到我們的需求,除了 data 以外也包含了 methods 可以共用,舉例來說,學生資料可能會在,班級跟社團內被使用,當我們要撰寫元件時,就可以省略多餘的 data 定義。
Thumbnail
本章節旨在介紹JavaScript中的物件導向編程。內容包括類別(Class)的定義和使用,建構子的作用,以及公開,私有,受保護(Protected)等不同訪問修飾符的概念。此外,還涵蓋了繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda表達式、泛型、反射等物件導向的主要觀念。
上一篇文章提到有些介面不應被繼承,但物件導向的子類別只能繼承父類別的介面,因而產生一些不合適的介面實作。trait/typeclass則沒有這種繼承機制,這似乎使需要繼承的特性無法直接使用。然而函數式導向比起繼承,更適合使用組合,根本不需要使用繼承疊加特性。 資料類型的定義往往跟怎麼建構模型相