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

React TS实现动态容器空间不足时显示+N项的需求

实现动态判断容器空间的Item渲染方案

完全可以实现这种动态判断需求,不用固定显示数量。核心思路是通过DOM尺寸计算,在容器尺寸变化时动态统计能容纳的Item数量,剩下的用“+X”替代。以下是具体的React TypeScript实现方案:

实现步骤与代码示例

我们需要借助useRef获取容器和Item的DOM节点,用useState保存可显示的Item数量,再通过useEffect监听容器尺寸变化并执行计算逻辑:

import { FC, useState, useRef, useEffect } from 'react';

// 假设Props定义如下
interface Props {
  items: { name: string }[];
}

// 模拟Item组件(根据你的实际组件调整样式)
const Item: FC<{ children: string }> = ({ children }) => {
  return <span style={{ display: 'inline-block', margin: '0 8px', padding: '4px 8px', border: '1px solid #eee', borderRadius: '4px' }}>{children}</span>;
};

// 容器组件(根据你的实际样式调整)
const ItemsContainer = ({ children }: { children: React.ReactNode }) => {
  return <div style={{ width: '100%', overflow: 'hidden', whiteSpace: 'nowrap' }}>{children}</div>;
};

const Items: FC<Props> = ({ items }) => {
  const [visibleCount, setVisibleCount] = useState(0);
  const containerRef = useRef<HTMLDivElement>(null);
  const itemRefs = useRef<(HTMLSpanElement | null)[]>([]);

  // 计算可显示的Item数量
  const calculateVisibleItems = () => {
    if (!containerRef.current) return;

    const containerWidth = containerRef.current.offsetWidth;
    let totalWidth = 0;
    let count = 0;

    // 先预计算"+X"组件的宽度,避免最后放不下这个标记
    const moreElement = document.createElement('span');
    moreElement.style.cssText = 'display: inline-block; margin: 0 8px; padding: 4px 8px; border: 1px solid #eee; border-radius: 4px;';
    moreElement.textContent = '+0';
    document.body.appendChild(moreElement);
    const moreWidth = moreElement.offsetWidth;
    document.body.removeChild(moreElement);

    // 遍历Item累加宽度,判断是否能容纳当前Item和"+X"组件
    for (let i = 0; i < items.length; i++) {
      const item = itemRefs.current[i];
      if (!item) continue;

      const itemWidth = item.offsetWidth;
      if (totalWidth + itemWidth + moreWidth <= containerWidth) {
        totalWidth += itemWidth;
        count++;
      } else {
        break;
      }
    }

    setVisibleCount(count);
  };

  useEffect(() => {
    // 初始渲染后执行一次计算
    calculateVisibleItems();

    // 监听窗口尺寸变化,重新计算
    window.addEventListener('resize', calculateVisibleItems);

    // 组件卸载时清理监听
    return () => {
      window.removeEventListener('resize', calculateVisibleItems);
    };
  }, [items]);

  const hasMore = visibleCount < items.length;
  const remainingCount = items.length - visibleCount;

  return (
    <ItemsContainer ref={containerRef}>
      {items.slice(0, visibleCount).map((item, index) => (
        <Item key={index} ref={(el) => (itemRefs.current[index] = el)}>
          {item.name}
        </Item>
      ))}
      {hasMore && <Item>+{remainingCount}</Item>}
    </ItemsContainer>
  );
};

export default Items;

关键细节说明

  • 尺寸计算逻辑:先预计算"+X"组件的宽度,确保最后有足够空间显示这个标记;然后逐个累加Item的宽度,直到加上当前Item和"+X"的总宽度超过容器宽度时停止。
  • 触发时机扩展:如果容器尺寸会因父组件变化、内容更新等非窗口resize因素改变,可以替换为ResizeObserver监听容器本身的尺寸变化,适配更多场景。
  • Item引用管理:用itemRefs数组保存每个Item的DOM节点,方便获取每个Item的实际渲染宽度。

内容的提问来源于stack exchange,提问作者Kaffemakarn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:05:28