后台项目,使用Ant Design Pro, 有这样一个需求:有一个表格,宽度是自适应的,表格中有一列是备注,文本长度不定,咱们但愿在文本过长的时候,使用省略样式(ellipsis),同时鼠标悬浮时有提示框展现完整文本。javascript
我计划设计一个React Hooks组件,嵌在表格里面,实现文本的自适应省略样式。java
这一列咱们只能使用相对宽度,由于整个表格是自适应宽度的,若是用固定宽度,可能在大屏上,这一列显得很窄。 dom
这里我用百分比,同时在页面组件维护一个宽度状态,在mounted以后,按百分比计算这一列的宽度并更新状态,如:clientWidth * 0.2。另外,监听window resize事件,更新宽度状态。spa
列宽计算出来以后,会经过props传给组件,有了宽度,利用:text-overflow: ellipsis; 就能够实现动态宽度的文本省略了。设计
这个提示框是在超长时才有,不超长时是没有的。这个是比较麻烦的一点,由于你要知道当前是否是在超长省略状态,咱们须要这个状态来设置是否加提示框。 rest
为了实现这个功能,我加了两个Hooks状态:是否超长、文本真实宽度。code
这里我就直接贴代码了,在后面会理一下关键点。对象
export default function LineEllipsis(props) { const { children, width = '200px', ...restProps } = props; const [textWidth, setTextWidth] = useState(0); const [isOverflow, setIsOverflow] = useState(false); const textRef = useRef(null); const textStyles = { width, display: 'inline-block', overflow: 'hidden', wordWrap: 'nowrap', textOverflow: 'ellipsis', }; useEffect( () => { if (textRef) { const { current } = textRef; const clientWidth = current.clientWidth; setTextWidth(clientWidth); if (!isOverflow && clientWidth > parseInt(width)) { setIsOverflow(true); } else if (isOverflow && clientWidth < parseInt(width)) { setIsOverflow(false); } } }, [children] ); useEffect( () => { if (textRef && textWidth > 0) { if (!isOverflow && textWidth > parseInt(width)) { setIsOverflow(true); } else if (isOverflow && textWidth < parseInt(width)) { setIsOverflow(false); } } }, [width] ); const textRender = () => { return ( <span ref={textRef} style={isOverflow ? textStyles : { display: 'inline-block' }} {...restProps} > {children} </span> ); }; return ( <div style={{ width }}> {isOverflow ? ( <Popover content={<pre className={styles.pop}>{children}</pre>}>{textRender()}</Popover> ) : ( textRender() )} </div> ); }
第二次使用React Hooks,确确实实感觉到了好处。事件
userEffect的依赖设置很是灵活好用。ip