覆寫元件結構
了解如何覆寫 Material UI 元件的預設 DOM 結構。
Material UI 元件旨在適用於最廣泛的使用情境,但您偶爾可能需要變更元件結構在 DOM 中的呈現方式。
為了理解如何做到這一點,了解 API 設計如何隨著時間演進,以及對元件本身有一個準確的心智模型會很有幫助。
背景脈絡
在 Material UI v6 之前,無法覆寫程式庫中大多數元件的結構。某些元件具有 *Props
props,可讓您將 props 傳遞到特定插槽,但此模式並未一致地應用。
在 v6 中,這些 props 已被棄用,轉而使用 slots
和 slotProps
props,它們可以更精細地控制元件的結構,並使整個程式庫的 API 更加一致。
心智模型
元件的結構由填充該元件插槽的元素決定。插槽最常由 HTML 標籤填充,但也可能由 React 元件填充。
所有元件都包含一個根插槽,該插槽定義了它們在 DOM 樹中的主要節點;更複雜的元件也包含額外的內部插槽,這些插槽以它們所代表的元素命名。
所有非工具 Material UI 元件都接受兩個 props 來覆寫其渲染的 HTML 結構
component
—覆寫根插槽slots
—替換任何內部插槽(如果存在)以及根插槽
此外,您可以使用 slotProps
將自訂 props 傳遞到內部插槽。
根插槽
根插槽代表元件的最外層元素。它由具有適當 HTML 元素的樣式化元件填充。
例如,Button 的根插槽是一個 <button>
元素。此元件僅有一個根插槽;更複雜的元件可能會有額外的內部插槽。
component prop
使用 component
prop 來覆寫元件的根插槽。下面的示範展示了如何將 Button 的 <button>
標籤替換為 <a>
以建立連結按鈕
內部插槽
複雜的元件由一個或多個內部插槽以及根插槽組成。這些插槽通常(但不一定)巢狀於根插槽內。
例如,Autocomplete 由一個根 <div>
組成,該根 <div>
容納了多個內部插槽,這些插槽以它們所代表的元素命名:input、startDecorator、endDecorator、clearIndicator、popupIndicator 等。
slots prop
使用 slots
prop 來替換元件的內部插槽。下面的範例展示了如何替換 Autocomplete 元件中的 popper 插槽以移除彈出功能
slotProps prop
slotProps
prop 是一個物件,其中包含元件內所有插槽的 props。您可以使用它來定義其他自訂 props,以傳遞到元件的內部插槽。
例如,下面的程式碼片段展示了如何將自訂 data-testid
新增到 Autocomplete 元件的 popper 插槽
<Autocomplete slotProps={{ popper: { 'data-testid': 'my-popper' } }} />
放置在主要元件上的所有其他 props 也會傳播到根插槽中(就像它們被放置在 slotProps.root
中一樣)。以下兩個範例是等效的
<Autocomplete id="badge1">
<Autocomplete slotProps={{ root: { id: 'badge1' } }}>
最佳實務
當您需要覆寫元素同時保留插槽的樣式時,請使用 component
或 slotProps.{slot}.component
prop。
當您需要使用自訂元件替換插槽的樣式和功能時,請使用 slots
prop。
使用 component
覆寫可讓您將該元素的屬性直接應用於根元素。例如,如果您使用 <li>
標籤覆寫 Button 的根元素,您可以將 <li>
屬性 value
直接新增到元件。如果您使用 slots.root
執行相同的操作,則需要將此屬性放置在 slotProps.root
物件上,以避免 TypeScript 錯誤。
在覆寫更複雜元件的插槽時,請注意您渲染的 DOM 結構。如果您過度偏離預設結構,您很容易破壞語意和可存取 HTML 的規則—例如,無意中將區塊層級元素巢狀於行內元素內部。