我们在使用 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包裹。
