我们在使用 Ant Design 的 Typography.Paragraph
时,发现其可以很友好地实现:
- 在文案未溢出时,不会渲染 tooltip
- 在文案溢出时,hover 才会显示 tooltip
具体来说,Ant Design 的 Typography.Paragraph
组件底层是基于 CSS 和 JavaScript 实现的,其 ellipsis
属性用于支持单行或多行的省略号显示,以及可选的 Tooltip
提示功能。
Paragraph
的底层实现解析
1. ellipsis
属性的核心逻辑
Typography.Paragraph
的 ellipsis
功能通过以下方式实现:
-
单行溢出:
通过 CSS 实现简单的单行省略号功能。white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
-
多行溢出:
使用 CSS 的-webkit-line-clamp
属性实现多行省略效果,结合display: -webkit-box
和-webkit-box-orient: vertical
。display: -webkit-box; -webkit-line-clamp: 2; /* 限制为两行 */ -webkit-box-orient: vertical; overflow: hidden;
注意:
-webkit-line-clamp
是一种非标准属性,主要支持 Webkit 内核浏览器。
2. Tooltip
动态检测溢出
当 ellipsis={{ tooltip: true }}
时,Ant Design 会启用 JavaScript 检测内容是否溢出。其内部实现大致如下:
-
使用 DOM 属性检测:
- 通过对
scrollWidth
和clientWidth
(单行)或scrollHeight
和clientHeight
(多行)的比较,判断是否存在溢出。 - 如果溢出,显示
Tooltip
。
const isOverflow = element.scrollWidth > element.clientWidth; // 单行 const isOverflow = element.scrollHeight > element.clientHeight; // 多行
- 通过对
-
渲染 Tooltip:
如果检测到内容溢出,则在Paragraph
外层动态包裹Tooltip
,Tooltip
的title
设置为完整文本。const shouldShowTooltip = isOverflow(); return (<Tooltip title={shouldShowTooltip ? text : undefined}><Paragraph>{text}</Paragraph></Tooltip> );
3. ellipsis
的实现组件
- Ant Design 使用了一个独立的工具函数
rc-util/lib/Dom/overflow
来封装 DOM 溢出检测。 - 该函数会在组件渲染后,通过
ref
获取 DOM 节点,并检测溢出状态。
Ant Design 的 Paragraph
核心代码实现(简化)
以下是 Typography.Paragraph
的简化实现:
import React, { useRef, useEffect, useState } from "react";
import { Tooltip } from "antd";const Paragraph = ({ text, ellipsis }) => {const paragraphRef = useRef(null);const [isOverflow, setIsOverflow] = useState(false);useEffect(() => {if (ellipsis) {const element = paragraphRef.current;if (element) {// 检测是否溢出const isOverflowing =element.scrollWidth > element.clientWidth ||element.scrollHeight > element.clientHeight;setIsOverflow(isOverflowing);}}}, [text, ellipsis]);return ellipsis?.tooltip && isOverflow ? (<Tooltip title={text}><divref={paragraphRef}style={{whiteSpace: ellipsis.rows ? "normal" : "nowrap",overflow: "hidden",textOverflow: "ellipsis",display: ellipsis.rows ? "-webkit-box" : "block",WebkitLineClamp: ellipsis.rows,WebkitBoxOrient: "vertical",}}>{text}</div></Tooltip>) : (<divref={paragraphRef}style={{whiteSpace: ellipsis?.rows ? "normal" : "nowrap",overflow: "hidden",textOverflow: "ellipsis",display: ellipsis?.rows ? "-webkit-box" : "block",WebkitLineClamp: ellipsis?.rows,WebkitBoxOrient: "vertical",}}>{text}</div>);
};export default Paragraph;
总结
- CSS 控制:
Paragraph
使用text-overflow: ellipsis
和-webkit-line-clamp
实现溢出隐藏和省略号。 - JavaScript 检测:通过 DOM 属性(如
scrollWidth
)检测内容溢出,并动态决定是否渲染Tooltip
。 - 动态渲染:根据
ellipsis.tooltip
配置,决定是否启用Tooltip
包裹。