Material UI与React:如何避免Autocomplete弹窗在子输入框聚焦时关闭
你遇到的问题是Material-UI的useAutocomplete默认会监听焦点离开事件,只要焦点移出Autocomplete的内部DOM区域,就会自动关闭弹窗。你弹出的Popper组件不属于Autocomplete的内部DOM层级,所以点击或聚焦Popper内的输入框时,会触发Autocomplete的失焦判定,导致弹窗关闭。
解决方法
1. 改为受控模式管理Autocomplete显隐
不要让useAutocomplete内部管理弹窗状态,改为自己通过state控制,同时拦截默认的关闭逻辑,仅在符合预期的场景下关闭弹窗。
首先新增控制Autocomplete显隐的状态:
const [autoCompleteOpen, setAutoCompleteOpen] = useState(false);
然后修改useAutocomplete的配置项:
const { getRootProps, getInputLabelProps, getInputProps, getListboxProps, getOptionProps, groupedOptions } = useAutocomplete({ id: "use-autocomplete-demo", options: countries, getOptionLabel: (option) => option.label, disableCloseOnSelect: true, // 新增受控配置 open: autoCompleteOpen, onOpen: () => setAutoCompleteOpen(true), onClose: (event, reason) => { // 仅按ESC键、或者点击Autocomplete和Popper外的区域时才关闭 if (reason === "escape") { setAutoCompleteOpen(false); return; } // 选择选项、点击输入框时不关闭 if (reason === "selectOption" || reason === "toggleInput") return; // 校验当前焦点/点击区域是否在Autocomplete或你的Popper内 const target = event.relatedTarget || event.target; const isInAutoComplete = document.getElementById("use-autocomplete-demo")?.contains(target); // 这里替换为你的Popper组件的类名/ID选择器 const isInPopper = target?.closest(".custom-popper-class"); if (!isInAutoComplete && !isInPopper) { setAutoCompleteOpen(false); } }, });
2. 给Popper内的输入框添加事件拦截
避免点击输入框时触发Autocomplete的失焦判定,给Popper里的InputBase添加如下属性:
<InputBase autoFocus onMouseDown={(e) => { // 阻止mousedown默认行为,避免先触发Autocomplete的失焦事件 e.preventDefault(); e.stopPropagation(); }} />
3. 可选:调整Popper的挂载容器
如果不想改事件逻辑,也可以把Popper的container属性设置为Autocomplete的根DOM节点,让Popper成为Autocomplete的子元素,这样点击Popper内部时,Autocomplete会判定为内部交互,不会触发失焦关闭。
内容的提问来源于stack exchange,提问作者UK4
相关产品推荐
相关产品推荐

