後臺項目,使用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