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
相关产品推荐
相关产品推荐

