React中如何获取自定义下拉组件的实际高度?
自定义下拉组件动态获取实际展开高度方案
我正在开发自定义下拉组件,目前通过以下方式控制下拉框高度:
maxHeight: dropDownOpen ? '600px' : '24px'
dropDownOpen是控制展开/收起的状态,但因为设置了height: 'min-content',下拉框实际不会展开到600px——关闭状态高度为24px(子div高度),展开时高度由内容自动适配(比如蓝色菜单实际为323.5px,红色菜单为203.5px)。过大的maxHeight会影响动画速度,希望能准确获取展开后的实际高度并动态设置。
解决方案代码
通过useRef获取DOM元素、useEffect监听状态变化,动态计算并设置实际展开高度:
export default function JSelect({ options, primaryColor, textColor, width }: JSelectProps) { const defaultValue = 4; const [currentOption, setCurrentOption] = React.useState(defaultValue); const [dropDownOpen, setDropDownOpen] = React.useState(false); // 存储展开后的实际高度 const [expandedHeight, setExpandedHeight] = React.useState('24px'); // 获取下拉框DOM引用 const menuRef = React.useRef<HTMLDivElement>(null); // Styles const buttonstyle: React.CSSProperties = { display: 'flex', alignItems: 'center', justifyContent: 'flex-start', width: width }; const menustyle: React.CSSProperties = { backgroundColor: hoverState, //primaryColor color: textColor, height: 'min-content', fontWeight: '700', fontSize: '20px', padding: '5px 15px', borderRadius: '20px', transition: 'background-color 0.2s ease, max-height 0.5s ease', // 动态使用计算出的实际高度 maxHeight: dropDownOpen ? expandedHeight : '24px', cursor: 'pointer', overflow: 'hidden', userSelect: 'none' }; // 监听展开状态变化,计算实际高度 React.useEffect(() => { if (dropDownOpen && menuRef.current) { // 用requestAnimationFrame确保DOM更新完成后再计算高度 requestAnimationFrame(() => { if (menuRef.current) { // scrollHeight获取包含padding的实际内容高度 setExpandedHeight(`${menuRef.current.scrollHeight}px`); } }); } else { // 收起时重置高度 setExpandedHeight('24px'); } }, [dropDownOpen]); function toggleDropDown(): void { setDropDownOpen(prev => !prev) } const optionElements: any = options.map((item, index) => { return ( <div onClick={() => setCurrentOption(item.value)} onMouseEnter={() => makeThisHover(index)} style={{ color: optionsHover[index] ? lightenColor(textColor) : textColor }} >{item.label}</div>) }) return ( {/* 绑定DOM引用 */} <div ref={menuRef} style={menustyle} onMouseEnter={onHover} onMouseLeave={onHoverExit} onClick={toggleDropDown} > <div style={buttonstyle}> {options[options.findIndex(item => item.value === currentOption)].label} <div style={{ height: '15px', display: 'flex', transform: dropDownOpen ? '' : 'rotate(-180deg)', transition: 'transform 250ms ease', marginLeft: 'auto' }}> <DropDownArrow fill="currentColor" /> </div> </div> <div style={{ height: '1.5px', backgroundColor: textColor, margin: '5px 0px' }} /> <div>{optionElements}</div> </div> ); }
方案说明
- 用
useRef绑定下拉框容器,直接读取DOM的实际高度属性 - 新增
expandedHeight状态存储计算后的准确高度,避免硬编码固定值 - 通过
requestAnimationFrame确保DOM完全更新后再计算高度,保证数值准确 - 收起时重置高度为24px,维持原有的关闭状态样式
内容的提问来源于stack exchange,提问作者Josh Silveous
相关产品推荐
相关产品推荐

