前言
在前端开发中,我们经常会遇到接口返回的文本内容过长,无法完全显示的问题。为了处理这一问题,通常会设置固定的宽度并使用省略号样式(text-overflow: ellipsis
)来隐藏超出的文本。然而,有时产品需求还希望用户能够通过悬停查看完整内容,这时就需要引入 Tooltip 进行展示。(没被省略的时候不要显示Tooltip)
css
// tailwind的样式单行省略
.line-clamp-1 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
// 自行设置的css样式
single-line {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
为了解决这个问题,我们实现了一个自定义 Hook,该 Hook 会监测文本元素是否因宽度限制而被省略。一旦检测到文本内容被省略,Hook 会自动为该元素添加 Tooltip,确保用户可以方便地查看完整信息。
代码实现
use-ellipsis.ts
ts
import { useEffect, useRef, useState } from 'react';
type Options = {
lines?: number; // 支持多行
};
export function useEllipsis<T extends HTMLElement>({
lines = 1,
}: Options = {}) {
const ref = useRef<T>(null);
const [isEllipsis, setIsEllipsis] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el) return;
const check = () => {
if (lines === 1) {
setIsEllipsis(el.scrollWidth > el.clientWidth);
} else {
setIsEllipsis(el.scrollHeight > el.clientHeight);
}
};
check();
window.addEventListener('resize', check);
return () => {
window.removeEventListener('resize', check);
};
}, [lines]);
return { ref, isEllipsis };
}
ellipsis-tooltip.tsx
tsx
import { Tooltip } from '@arco-design/web-react'; // 或 antd / 你自己的库
import { useEllipsis } from '@/hooks/use-ellipsis.ts';
import { cn } from '@/lib/utils.ts';
type EllipsisTooltipProps = {
text: string;
className?: string;
onClick?: () => void;
lines?: number;
};
export const EllipsisTooltip: React.FC<EllipsisTooltipProps> = ({
text,
className,
onClick,
lines = 1,
}) => {
const { ref, isEllipsis } = useEllipsis<HTMLDivElement>({ lines });
const lineClass =
lines === 1 ? 'truncate whitespace-nowrap' : `line-clamp-${lines}`;
const content = (
<div ref={ref} className={cn(lineClass, className)} onClick={onClick}>
{text}
</div>
);
return isEllipsis ? <Tooltip content={text}>{content}</Tooltip> : content;
};
使用
tsx
<EllipsisTooltip
text={text}
className="text-blue-500 flex-1 min-w-0 hover:cursor-pointer"
onClick={}
/>