You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 08:06:19