選單
下拉式選單組件為終端使用者在暫時性介面上提供選項列表。
簡介
MUI Base 下拉式選單是使用相關組件的集合來實作的
- Dropdown - 容納所有選單組件的最外層容器。
- 選單按鈕 - 切換選單可見性的按鈕。
- 選單 - 選單項目的無序列表。
- 選單項目 - 選單的個別列表項目。
組件
import { Dropdown } from '@mui/base/Dropdown';
import { MenuButton } from '@mui/base/MenuButton';
import { Menu } from '@mui/base/Menu';
import { MenuItem } from '@mui/base/MenuItem';
下面的示範展示如何建立和樣式化下拉式選單。點擊儀表板以查看選單。請注意,它使用內建的 Popper 組件,以便在視覺上跳脫其父容器
<Dropdown />
應該是最外層的組件—所有其他選單相關的組件都必須放置為其子元件(但不一定是直接子元件)。如果您需要控制選單的開啟狀態或對其變更做出反應,請將 open
/onOpenChange
屬性放置在 <Dropdown />
上。
<Dropdown />
必須僅包含一個 <MenuButton />
和一個 <Menu />
。它會將它們連接在一起,以便按下按鈕將開啟選單。它還負責分配適當的輔助功能屬性,以便下拉式選單可以與輔助技術或鍵盤一起使用。
<Menu />
託管的 <MenuItem />
組件可以包裝在任意標籤和組件中,也可以分組在一起。點擊選單項目會關閉其關聯的選單。
結構
<Dropdown />
不會渲染任何 HTML 元素—它僅提供將選單按鈕連結到選單的上下文,因此您不必這樣做。<MenuButton />
渲染一個<button>
。<Menu />
組件渲染一個<div>
,其中包含一個巢狀的<ul>
。<MenuItem />
渲染一個<li>
。
<button class="base-MenuButton-root">Click me</button>
<div class="base-Menu-root">
<ul class="base-Menu-listbox">
<li class="base-MenuItem-root">List item</li>
</ul>
</div>
自訂結構
使用 slots
屬性來覆寫除 <Dropdown />
之外的任何組件上的插槽(因為它不渲染任何 HTML)
<Menu slots={{ listbox: 'ol' }} />
使用 slotProps
屬性將自訂屬性傳遞到內部插槽。以下程式碼片段將名為 my-listbox
的 CSS 類別套用到選單上的 listbox 插槽
<Menu slotProps={{ listbox: { className: 'my-listbox' } }} />
與 TypeScript 一起使用
在 TypeScript 中,您可以將 slots.root
中使用的自訂組件類型指定為非樣式化組件的泛型參數。這樣,您可以安全地在組件上直接提供自訂根目錄的屬性
<Menu<typeof CustomComponent> slots={{ root: CustomComponent }} customProp />
這同樣適用於特定於自訂原始元素的屬性
<Menu<'ol'> slots={{ root: 'ol' }} start={5} />
轉場效果
選單組件支援 Transitions API,因此可以動畫呈現和隱藏 Listbox。若要執行此操作,請覆寫選單的 Listbox 插槽,並使用轉場效果組件(CssTransition、CssAnimation 或自訂建置的組件)包裝它。
Hook
import { useDropdown } from '@mui/base/useDropdown';
import { useMenuButton } from '@mui/base/useMenuButton';
import { useMenu } from '@mui/base/useMenu';
import { useMenuItem } from '@mui/base/useMenuItem';
下拉式選單 Hook 可讓您將下拉式選單套件的功能應用於完全自訂的組件。它們傳回要放置在自訂組件上的屬性,以及代表組件內部狀態的欄位。
以下示範展示如何使用 Hook 建置下拉式選單
組件及其對應的 Hook 可以彼此互換使用—例如,您可以建立一個包含使用 useMenuItem
Hook 建置的自訂選單項目的選單組件。
效能
useMenuItem
Hook 監聽由父選單組件設定的上下文中的變更。此上下文在每次項目醒目提示時都會變更。通常,這不應該是一個問題,但是,當您的選單有數百個項目時,您可能會注意到它不是很反應靈敏,因為每次醒目提示變更時,每個項目都會重新渲染。
為了透過防止選單項目不必要地渲染來提高效能,您可以建立一個包裝選單項目的組件。在此組件內部,呼叫 useMenuItemContextStabilizer
並使用 Hook 結果中的值建立 ListContext
const StableMenuItem = React.forwardRef(function StableMenuItem(
props: MenuItemProps,
ref: React.ForwardedRef<Element>,
) {
const { contextValue, id } = useMenuItemContextStabilizer(props.id);
return (
<ListContext.Provider value={contextValue}>
<MenuItem {...props} id={id} ref={ref} />
</ListContext.Provider>
);
});
useMenuItemContextStabilizer
Hook 可確保上下文值僅在選單項目的狀態更新時才會變更。
自訂
包裝選單項目
選單項目組件不必是選單組件的直接子元件。您可以將它們包裝在所需的任何組件中,以達到所需的樣式外觀。
除了選單項目組件之外,選單組件還可以包含非互動式子元件,例如輔助文字。
以下示範顯示了一個下拉式選單的範例,其中的項目分組在非互動式標題下,以及顯示目前縮放比例的輔助文字