javascript
/** hooks
* 用于文本展示时判断是否展示 展开/收起按钮 (包含监听 文本变化/页面尺寸变换)
* @param { string } text 需要展示的文本
* @param { number } maxLength 文本最大展示行数
* @param { number } lineHeight 文本行高 (单位 px)
*/
import React, { useEffect, useRef, useState } from 'react';
export const TruncatedText = ({ text,lineHeight,maxLength }) => {
// 用于判断目前展开与否
const [isTruncated, setIsTruncated] = useState(true);
//是否需要显示 展开收起按钮
const [shouldShowMore, setShouldShowMore] = useState(false);
const containerRef = useRef(null);
useEffect(() => {
const checkTruncation = () => {
if (containerRef.current) {
const { scrollHeight } = containerRef.current;
setShouldShowMore(scrollHeight > lineHeight*maxLength);
}
};
checkTruncation(); // 初次检查
// 监听页面缩放
const resizeObserver = new ResizeObserver(checkTruncation);
if (containerRef.current) {
resizeObserver.observe(containerRef.current);
}
return () => {
if (containerRef.current) {
resizeObserver.unobserve(containerRef.current);
}
};
}, [text]);
const toggleTruncate = () => {
setIsTruncated((prev) => !prev);
};
return (
<div
style={{
position: 'relative',
display: '-webkit-box',
overflow: 'hidden',
maxHeight: isTruncated ? `calc(${lineHeight}px * ${maxLength})` : 'none',
transition: 'max-height 0.2s ease',
fontSize: '14px',
lineHeight: `${lineHeight}px`,
}}
>
<span ref={containerRef} style={{display:'inline-block'}} >
{text}
</span>
{shouldShowMore && (
<a
onClick={toggleTruncate}
style={{
background: '#fff',
position: 'absolute',
bottom: 0,
right: 0,
}}
>
{isTruncated ? ' -展开' : '收起'}
</a>
)}
</div>
);
};