如何实现选择选项时保持下拉列表展开的Fluent UI组件?
问题描述
需要创建一个满足以下要求的下拉控件:
- 包含一个按钮,点击可展开选项列表
- 点击选项能完成选择并同步通知父组件
- 仅点击列表外部区域(或再次点击按钮)才关闭列表,选择选项后列表保持展开
目前使用Fluent UI的Dropdown组件实现了基础下拉功能,但默认选中选项后列表会自动关闭,不符合需求。注意到受控多选Dropdown的默认行为就是点击外部才关闭,因此该需求具备可行性。接受Fabric UI、Fluent UI、Material UI等库中的Dropdown/Select/Combobox控件。
现有代码如下:
import React from "react"; import { Dropdown } from "@fluentui/react/lib/Dropdown"; import { initializeIcons } from "@fluentui/react/lib/Icons"; initializeIcons(); const numberOptions = [8, 9, 10].map((i) => ({ key: i, text: "Number: " + i.toString() })); export default class App extends React.Component { constructor(props) { super(props); this.state = { number: 8 }; } onnumberChange = (_ev, option) => { if (typeof option.key === "number") { this.setState({ number: option.key }); } }; render() { return ( <div> {`Number: ${this.state.number}`} <br /> <br /> <Dropdown options={numberOptions} defaultSelectedKey={this.state.number} onChange={this.onnumberChange} /> </div> ); } }
解决方案
基于Fluent UI修改实现
要实现选择选项后保持列表展开,需将Dropdown设置为受控模式,手动控制展开/收起状态,不在选项选中时自动关闭。
修改思路:
- 在组件state中添加
isDropdownOpen字段,控制列表展开状态 - 使用Dropdown的
open属性绑定该状态 - 监听Dropdown的
onToggle事件,更新展开状态(点击按钮或外部区域时触发) - 在
onChange事件中仅更新选中值,不修改展开状态
修改后的代码:
import React from "react"; import { Dropdown } from "@fluentui/react/lib/Dropdown"; import { initializeIcons } from "@fluentui/react/lib/Icons"; initializeIcons(); const numberOptions = [8, 9, 10].map((i) => ({ key: i, text: "Number: " + i.toString() })); export default class App extends React.Component { constructor(props) { super(props); this.state = { number: 8, isDropdownOpen: false // 新增状态控制展开 }; } onnumberChange = (_ev, option) => { if (typeof option.key === "number") { // 仅更新选中值,不修改展开状态 this.setState({ number: option.key }); } }; onDropdownToggle = (_ev, isOpen) => { // 手动更新展开状态 this.setState({ isDropdownOpen: isOpen }); }; render() { return ( <div> {`Number: ${this.state.number}`} <br /> <br /> <Dropdown options={numberOptions} selectedKey={this.state.number} // 改为受控模式,绑定选中值 open={this.state.isDropdownOpen} // 绑定展开状态 onChange={this.onnumberChange} onToggle={this.onDropdownToggle} // 监听展开/收起事件 /> </div> ); } }
基于Material UI实现(备选方案)
如果使用Material UI的Select组件,同样可以通过受控模式控制菜单展开状态,配合MenuProps配置阻止选中时关闭菜单:
import React from "react"; import { Select, MenuItem, FormControl, InputLabel } from "@mui/material"; const numberOptions = [8, 9, 10]; export default class App extends React.Component { constructor(props) { super(props); this.state = { number: 8, isMenuOpen: false }; } handleChange = (event) => { this.setState({ number: event.target.value }); }; handleMenuOpen = () => { this.setState({ isMenuOpen: true }); }; handleMenuClose = () => { this.setState({ isMenuOpen: false }); }; render() { return ( <div> {`Number: ${this.state.number}`} <br /> <br /> <FormControl sx={{ m: 1, minWidth: 120 }}> <InputLabel id="number-select-label">Number</InputLabel> <Select labelId="number-select-label" value={this.state.number} label="Number" onChange={this.handleChange} open={this.state.isMenuOpen} onOpen={this.handleMenuOpen} onClose={this.handleMenuClose} MenuProps={{ // 配置菜单选中时不自动关闭 onItemClick: (event) => { event.preventDefault(); // 阻止默认关闭行为 } }} > {numberOptions.map(num => ( <MenuItem key={num} value={num}>Number: {num}</MenuItem> ))} </Select> </FormControl> </div> ); } }
内容的提问来源于stack exchange,提问作者SoftTimur
相关产品推荐
相关产品推荐

