跳到主要內容
+

選單

下拉式選單組件為終端使用者在暫時性介面上提供選項列表。

簡介

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 組件,以便在視覺上跳脫其父容器

按下 Enter 開始編輯

<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 插槽,並使用轉場效果組件(CssTransitionCssAnimation 或自訂建置的組件)包裝它。

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 建置下拉式選單

按下 Enter 開始編輯

組件及其對應的 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 可確保上下文值僅在選單項目的狀態更新時才會變更。

自訂

包裝選單項目

選單項目組件不必是選單組件的直接子元件。您可以將它們包裝在所需的任何組件中,以達到所需的樣式外觀。

除了選單項目組件之外,選單組件還可以包含非互動式子元件,例如輔助文字。

以下示範顯示了一個下拉式選單的範例,其中的項目分組在非互動式標題下,以及顯示目前縮放比例的輔助文字