跳到主要內容
+

覆寫元件結構

了解如何覆寫 Material UI 元件的預設 DOM 結構。

Material UI 元件旨在適用於最廣泛的使用情境,但您偶爾可能需要變更元件結構在 DOM 中的呈現方式。

為了理解如何做到這一點,了解 API 設計如何隨著時間演進,以及對元件本身有一個準確的心智模型會很有幫助。

背景脈絡

在 Material UI v6 之前,無法覆寫程式庫中大多數元件的結構。某些元件具有 *Props props,可讓您將 props 傳遞到特定插槽,但此模式並未一致地應用。

在 v6 中,這些 props 已被棄用,轉而使用 slotsslotProps props,它們可以更精細地控制元件的結構,並使整個程式庫的 API 更加一致。

心智模型

元件的結構由填充該元件插槽的元素決定。插槽最常由 HTML 標籤填充,但也可能由 React 元件填充。

所有元件都包含一個根插槽,該插槽定義了它們在 DOM 樹中的主要節點;更複雜的元件也包含額外的內部插槽,這些插槽以它們所代表的元素命名。

所有非工具 Material UI 元件都接受兩個 props 來覆寫其渲染的 HTML 結構

  • component—覆寫根插槽
  • slots—替換任何內部插槽(如果存在)以及根插槽

此外,您可以使用 slotProps 將自訂 props 傳遞到內部插槽。

根插槽

根插槽代表元件的最外層元素。它由具有適當 HTML 元素的樣式化元件填充。

例如,Button 的根插槽是一個 <button> 元素。此元件有一個根插槽;更複雜的元件可能會有額外的內部插槽

component prop

使用 component prop 來覆寫元件的根插槽。下面的示範展示了如何將 Button 的 <button> 標籤替換為 <a> 以建立連結按鈕

按下 Enter 開始編輯

內部插槽

複雜的元件由一個或多個內部插槽以及根插槽組成。這些插槽通常(但不一定)巢狀於根插槽內。

例如,Autocomplete 由一個根 <div> 組成,該根 <div> 容納了多個內部插槽,這些插槽以它們所代表的元素命名:input、startDecorator、endDecorator、clearIndicator、popupIndicator 等。

slots prop

使用 slots prop 來替換元件的內部插槽。下面的範例展示了如何替換 Autocomplete 元件中的 popper 插槽以移除彈出功能

按下 Enter 開始編輯

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' } }}>

最佳實務

當您需要覆寫元素同時保留插槽的樣式時,請使用 componentslotProps.{slot}.component prop。

當您需要使用自訂元件替換插槽的樣式和功能時,請使用 slots prop。

使用 component 覆寫可讓您將該元素的屬性直接應用於根元素。例如,如果您使用 <li> 標籤覆寫 Button 的根元素,您可以將 <li> 屬性 value 直接新增到元件。如果您使用 slots.root 執行相同的操作,則需要將此屬性放置在 slotProps.root 物件上,以避免 TypeScript 錯誤。

在覆寫更複雜元件的插槽時,請注意您渲染的 DOM 結構。如果您過度偏離預設結構,您很容易破壞語意和可存取 HTML 的規則—例如,無意中將區塊層級元素巢狀於行內元素內部。