下拉菜单
使用 Bootstrap 下拉菜单插件切换上下文覆盖层以显示链接列表等
概述
下拉菜单是用于显示链接列表等的可切换上下文覆盖层。与覆盖层一样,下拉菜单是使用第三方库 Popper.js 构建的,该库提供动态定位和视口检测。
无障碍性
该 WAI ARIA 标准定义了一个 role="menu"
小部件,但它非常特定于某种菜单。 ARIA 菜单必须仅包含 role="menuitem"
、role="menuitemcheckbox"
或 role="menuitemradio"
。
另一方面,Bootstrap 的下拉菜单旨在更通用,并在各种情况下应用。出于这个原因,我们不会自动将菜单角色添加到标记中。我们确实实现了一些基本的键盘导航,如果您确实提供了“菜单”角色,react-bootstrap 将尽力确保焦点管理符合 ARIA 菜单的作者指南。
示例
单按钮下拉菜单
基本的下拉菜单由一个包裹的 Dropdown
和内部的 <DropdownMenu>
以及 <DropdownToggle>
组成。默认情况下,<DropdownToggle>
将渲染一个 Button
组件,并接受所有相同的 props。
import Dropdown from 'react-bootstrap/Dropdown';function BasicExample() {return (<Dropdown><Dropdown.Toggle variant="success" id="dropdown-basic">Dropdown Button</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#/action-1">Action</Dropdown.Item><Dropdown.Item href="#/action-2">Another action</Dropdown.Item><Dropdown.Item href="#/action-3">Something else</Dropdown.Item></Dropdown.Menu></Dropdown>);}export default BasicExample;
由于以上配置非常常见,react-bootstrap 提供了 <DropdownButton>
组件来减少输入。提供一个 title
prop 和一些 <DropdownItem>
,你就可以开始使用了。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';function BasicButtonExample() {return (<DropdownButton id="dropdown-basic-button" title="Dropdown button"><Dropdown.Item href="#/action-1">Action</Dropdown.Item><Dropdown.Item href="#/action-2">Another action</Dropdown.Item><Dropdown.Item href="#/action-3">Something else</Dropdown.Item></DropdownButton>);}export default BasicButtonExample;
DropdownButton 将把 Button props 传递给底层的 Toggle 组件
import ButtonGroup from 'react-bootstrap/ButtonGroup';import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';function VariantsExample() {return (<>{['Primary', 'Secondary', 'Success', 'Info', 'Warning', 'Danger'].map((variant) => (<DropdownButtonas={ButtonGroup}key={variant}id={`dropdown-variants-${variant}`}variant={variant.toLowerCase()}title={variant}><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3" active>Active Item</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></DropdownButton>),)}</>);}export default VariantsExample;
分隔按钮下拉菜单
类似地,你可以通过将 Dropdown 组件与另一个 Button 和 ButtonGroup 组合来创建一个分隔下拉菜单。
import Button from 'react-bootstrap/Button';import ButtonGroup from 'react-bootstrap/ButtonGroup';import Dropdown from 'react-bootstrap/Dropdown';function SplitBasicExample() {return (<Dropdown as={ButtonGroup}><Button variant="success">Split Button</Button><Dropdown.Toggle split variant="success" id="dropdown-split-basic" /><Dropdown.Menu><Dropdown.Item href="#/action-1">Action</Dropdown.Item><Dropdown.Item href="#/action-2">Another action</Dropdown.Item><Dropdown.Item href="#/action-3">Something else</Dropdown.Item></Dropdown.Menu></Dropdown>);}export default SplitBasicExample;
与 DropdownButton 一样,SplitButton
作为便利组件提供。
import Dropdown from 'react-bootstrap/Dropdown';import SplitButton from 'react-bootstrap/SplitButton';function SplitVariantExample() {return (<>{['Primary', 'Secondary', 'Success', 'Info', 'Warning', 'Danger'].map((variant) => (<SplitButtonkey={variant}id={`dropdown-split-variants-${variant}`}variant={variant.toLowerCase()}title={variant}><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3" active>Active Item</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></SplitButton>),)}</>);}export default SplitVariantExample;
尺寸
下拉菜单适用于所有尺寸的按钮。
import ButtonGroup from 'react-bootstrap/ButtonGroup';import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';import SplitButton from 'react-bootstrap/SplitButton';function ButtonSizesExample() {return (<><div className="mb-2">{[DropdownButton, SplitButton].map((DropdownType, idx) => (<DropdownTypeas={ButtonGroup}key={idx}id={`dropdown-button-drop-${idx}`}size="lg"title="Drop large"><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></DropdownType>))}</div><div>{[DropdownButton, SplitButton].map((DropdownType, idx) => (<DropdownTypeas={ButtonGroup}key={idx}id={`dropdown-button-drop-${idx}`}size="sm"variant="secondary"title="Drop small"><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></DropdownType>))}</div></>);}export default ButtonSizesExample;
深色下拉菜单
通过在现有 DropdownMenu
上添加 variant="dark"
来选择更暗的下拉菜单,以匹配深色导航栏或自定义样式。或者,在使用 DropdownButton
组件时使用 menuVariant="dark"
。
Bootstrap v5.3.0 中引入了颜色模式,组件的深色变体已弃用。不再添加 variant="dark"
,而是将 data-bs-theme="dark"
设置在根元素、父包装器或组件本身。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';function ButtonDarkExample() {return (<><Dropdown data-bs-theme="dark"><Dropdown.Toggle id="dropdown-button-dark-example1" variant="secondary">Dropdown Button</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#/action-1" active>Action</Dropdown.Item><Dropdown.Item href="#/action-2">Another action</Dropdown.Item><Dropdown.Item href="#/action-3">Something else</Dropdown.Item><Dropdown.Divider /><Dropdown.Item href="#/action-4">Separated link</Dropdown.Item></Dropdown.Menu></Dropdown><DropdownButtonid="dropdown-button-dark-example2"variant="secondary"title="Dropdown button"className="mt-2"data-bs-theme="dark"><Dropdown.Item href="#/action-1" active>Action</Dropdown.Item><Dropdown.Item href="#/action-2">Another action</Dropdown.Item><Dropdown.Item href="#/action-3">Something else</Dropdown.Item><Dropdown.Divider /><Dropdown.Item href="#/action-4">Separated link</Dropdown.Item></DropdownButton></>);}export default ButtonDarkExample;
在 NavDropdown
中使用 menuVariant="dark"
import Container from 'react-bootstrap/Container';import Nav from 'react-bootstrap/Nav';import Navbar from 'react-bootstrap/Navbar';import NavDropdown from 'react-bootstrap/NavDropdown';function NavbarDarkExample() {return (<Navbar variant="dark" bg="dark" expand="lg"><Container fluid><Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand><Navbar.Toggle aria-controls="navbar-dark-example" /><Navbar.Collapse id="navbar-dark-example"><Nav><NavDropdownid="nav-dropdown-dark-example"title="Dropdown"menuVariant="dark"><NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item><NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item><NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item><NavDropdown.Divider /><NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item></NavDropdown></Nav></Navbar.Collapse></Container></Navbar>);}export default NavbarDarkExample;
下拉方向
使用 drop
prop,可以在其切换元素的上方、下方、左侧或右侧触发下拉菜单。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';import SplitButton from 'react-bootstrap/SplitButton';function DropDirectioExample() {return (<><div className="mb-2">{['up', 'up-centered', 'down', 'down-centered', 'start', 'end'].map((direction) => (<DropdownButtonas={ButtonGroup}key={direction}id={`dropdown-button-drop-${direction}`}drop={direction}variant="secondary"title={` Drop ${direction} `}><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></DropdownButton>),)}</div><div>{['up', 'up-centered', 'down', 'down-centered', 'start', 'end'].map((direction) => (<SplitButtonkey={direction}id={`dropdown-button-drop-${direction}`}drop={direction}variant="secondary"title={`Drop ${direction}`}><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></SplitButton>),)}</div></>);}export default DropDirectioExample;
下拉菜单项
历史上,下拉菜单内容必须是链接,但在 v4 中不再是这种情况。现在,你可以在下拉菜单中使用 <button>
元素,而不仅仅是 <a>
。
您也可以使用<Dropdown.ItemText>
创建非交互式下拉菜单项。您可以随意使用自定义 CSS 或文本实用程序进行进一步的样式设置。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';function DropdownItemTagsExample() {return (<DropdownButton id="dropdown-item-button" title="Dropdown button"><Dropdown.ItemText>Dropdown item text</Dropdown.ItemText><Dropdown.Item as="button">Action</Dropdown.Item><Dropdown.Item as="button">Another action</Dropdown.Item><Dropdown.Item as="button">Something else</Dropdown.Item></DropdownButton>);}export default DropdownItemTagsExample;
菜单对齐
默认情况下,下拉菜单向左对齐,但您可以通过将align="end"
传递给<Dropdown>
、<DropdownButton>
或<SplitButton>
来切换它。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';function MenuAlignEndExample() {return (<DropdownButtonalign="end"title="Dropdown end"id="dropdown-menu-align-end"><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></DropdownButton>);}export default MenuAlignEndExample;
响应式对齐
如果您想使用响应式菜单对齐,请将包含断点的对象传递给<DropdownMenu>
、<DropdownButton>
或<SplitButton>
上的align
道具。您可以为各种断点指定start
或end
。
使用响应式对齐将禁用 Popper 的使用,因此任何动态定位功能(如flip
)将无法使用。
import Dropdown from 'react-bootstrap/Dropdown';import DropdownButton from 'react-bootstrap/DropdownButton';import SplitButton from 'react-bootstrap/SplitButton';function MenuAlignResponsiveExample() {return (<><div><DropdownButtonas={ButtonGroup}align={{ lg: 'end' }}title="Left-aligned but right aligned when large screen"id="dropdown-menu-align-responsive-1"><Dropdown.Item eventKey="1">Action 1</Dropdown.Item><Dropdown.Item eventKey="2">Action 2</Dropdown.Item></DropdownButton></div><div className="mt-2"><SplitButtonalign={{ lg: 'start' }}title="Right-aligned but left aligned when large screen"id="dropdown-menu-align-responsive-2"><Dropdown.Item eventKey="1">Action 1</Dropdown.Item><Dropdown.Item eventKey="2">Action 2</Dropdown.Item></SplitButton></div></>);}export default MenuAlignResponsiveExample;
菜单标题
添加标题以标记操作部分。
import Dropdown from 'react-bootstrap/Dropdown';function MenuHeadersExample() {return (<Dropdown.Menu show><Dropdown.Header>Dropdown header</Dropdown.Header><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item></Dropdown.Menu>);}export default MenuHeadersExample;
菜单分隔符
使用分隔符将相关菜单项分组。
import Dropdown from 'react-bootstrap/Dropdown';function MenuDividersExample() {return (<Dropdown.Menu show><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3">Something else here</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></Dropdown.Menu>);}export default MenuDividersExample;
自动关闭
默认情况下,下拉菜单在选择菜单项或单击下拉菜单外部时关闭。可以使用autoClose
属性更改此行为。
默认情况下,autoClose
设置为默认值true
,并按预期工作。通过选择false
,下拉菜单只能通过单击下拉按钮来切换。inside
使下拉菜单仅通过选择菜单项消失,而outside
仅通过单击外部关闭下拉菜单。
注意在每种情况下,如何通过单击按钮来切换下拉菜单。
import Dropdown from 'react-bootstrap/Dropdown';function AutoCloseExample() {return (<><Dropdown className="d-inline mx-2"><Dropdown.Toggle id="dropdown-autoclose-true">Default Dropdown</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item></Dropdown.Menu></Dropdown><Dropdown className="d-inline mx-2" autoClose="inside"><Dropdown.Toggle id="dropdown-autoclose-inside">Clickable Outside</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item></Dropdown.Menu></Dropdown><Dropdown className="d-inline mx-2" autoClose="outside"><Dropdown.Toggle id="dropdown-autoclose-outside">Clickable Inside</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item></Dropdown.Menu></Dropdown><Dropdown className="d-inline mx-2" autoClose={false}><Dropdown.Toggle id="dropdown-autoclose-false">Manual Close</Dropdown.Toggle><Dropdown.Menu><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item><Dropdown.Item href="#">Menu Item</Dropdown.Item></Dropdown.Menu></Dropdown></>);}export default AutoCloseExample;
自定义
如果下拉菜单和切换组件的默认处理不符合您的要求,您可以使用更基本的<Dropdown>
组件显式指定切换和菜单组件来对其进行自定义。
import Button from 'react-bootstrap/Button';import ButtonGroup from 'react-bootstrap/ButtonGroup';import Dropdown from 'react-bootstrap/Dropdown';function ButtonCustomExample() {return (<><Dropdown as={ButtonGroup}><Dropdown.Toggle id="dropdown-custom-1">Pow! Zoom!</Dropdown.Toggle><Dropdown.Menu className="super-colors"><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3" active>Active Item</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></Dropdown.Menu></Dropdown>{' '}<Dropdown as={ButtonGroup}><Button variant="info">mix it up style-wise</Button><Dropdown.Toggle split variant="success" id="dropdown-custom-2" /><Dropdown.Menu className="super-colors"><Dropdown.Item eventKey="1">Action</Dropdown.Item><Dropdown.Item eventKey="2">Another action</Dropdown.Item><Dropdown.Item eventKey="3" active>Active Item</Dropdown.Item><Dropdown.Divider /><Dropdown.Item eventKey="4">Separated link</Dropdown.Item></Dropdown.Menu></Dropdown></>);}export default ButtonCustomExample;
自定义下拉组件
对于那些想要自定义所有内容的用户,您可以放弃包含的 Toggle 和 Menu 组件,并创建自己的组件。通过向 as
属性提供自定义组件,您可以控制每个组件的行为。自定义的切换和菜单组件**必须**能够接受 refs。
import React, { useState } from 'react';import Dropdown from 'react-bootstrap/Dropdown';import Form from 'react-bootstrap/Form';// The forwardRef is important!!// Dropdown needs access to the DOM node in order to position the Menuconst CustomToggle = React.forwardRef(({ children, onClick }, ref) => (<ahref=""ref={ref}onClick={(e) => {e.preventDefault();onClick(e);}}>{children}▼</a>));// forwardRef again here!// Dropdown needs access to the DOM of the Menu to measure itconst CustomMenu = React.forwardRef(({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {const [value, setValue] = useState('');return (<divref={ref}style={style}className={className}aria-labelledby={labeledBy}><Form.ControlautoFocusclassName="mx-3 my-2 w-auto"placeholder="Type to filter..."onChange={(e) => setValue(e.target.value)}value={value}/><ul className="list-unstyled">{React.Children.toArray(children).filter((child) =>!value || child.props.children.toLowerCase().startsWith(value),)}</ul></div>);},);render(<Dropdown><Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components">Custom toggle</Dropdown.Toggle><Dropdown.Menu as={CustomMenu}><Dropdown.Item eventKey="1">Red</Dropdown.Item><Dropdown.Item eventKey="2">Blue</Dropdown.Item><Dropdown.Item eventKey="3" active>Orange</Dropdown.Item><Dropdown.Item eventKey="1">Red-Orange</Dropdown.Item></Dropdown.Menu></Dropdown>,);