如何在Material-UI的Autocomplete组件打开下拉时自动滚动到指定选项
实现方案
核心逻辑是监听下拉展开事件,在列表渲染完成后主动触发目标选项滚动到可视区顶部,无需修改原选项排序。
实现步骤
- 受控管理Autocomplete的
open状态,用于监听下拉框的展开时机 - 自定义
renderOption方法,给每个选项DOM添加唯一标识属性,方便快速定位目标元素 - 下拉框展开后,等待列表DOM渲染完成,查询到目标选项节点,调用
scrollIntoView方法滚动到容器顶部
完整实现代码
import * as React from 'react'; import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; import ListItem from '@mui/material/ListItem'; // 定义要定位的目标项 const TARGET_FILM = { label: 'Inception', year: 2010 }; export default function ComboBox() { const [open, setOpen] = React.useState(false); // 监听下拉展开状态,执行滚动逻辑 React.useEffect(() => { if (open) { // 加短延迟确保下拉列表DOM已渲染完成 setTimeout(() => { // 查找目标选项的DOM节点 const targetOption = document.querySelector(`[data-film-label="${TARGET_FILM.label}"]`); if (targetOption) { // block: 'start'表示对齐到可视区域顶部,刚好符合需求 targetOption.scrollIntoView({ block: 'start', inline: 'nearest' }); } }, 0); } }, [open]); return ( <Autocomplete disablePortal id="combo-box-demo" options={top100Films} sx={{ width: 300 }} // 受控管理open状态 open={open} onOpen={() => setOpen(true)} onClose={() => setOpen(false)} // 自定义渲染选项,添加唯一标识属性 renderOption={(props, option) => ( <ListItem {...props} data-film-label={option.label}> {option.label} ({option.year}) </ListItem> )} renderInput={(params) => <TextField {...params} label="Movie" />} /> ); } // Top 100 films as rated by IMDb users. const top100Films = [ { label: 'The Shawshank Redemption', year: 1994 }, { label: 'The Godfather', year: 1972 }, { label: 'The Dark Knight', year: 2008 }, { label: 'Inception', year: 2010 }, // 其余电影数据... ];
补充说明
如果存在label重复的情况,可以改用label + year的组合作为唯一标识,避免查询到错误节点;复杂渲染场景下可适当调大setTimeout的延迟时长到10~50ms,确保DOM渲染完成后再执行滚动逻辑。该方案完全不改动原选项排序,性能开销极低,是当前场景的最优实现。
内容的提问来源于stack exchange,提问作者Lutaaya Huzaifah Idris
相关产品推荐
相关产品推荐

