在 antd Table 中实现多行省略和 Tooltip

antd 的 Table 默认 ellipsis: true 只能单行省略。实际项目中,我们常常需要:

  • 多行文本超出时显示省略号
  • 可自定义行数
  • 仅在真正溢出时显示 Tooltip

1️⃣ EllipsisText.tsx(多行省略 + Tooltip 组件)

ini 复制代码
import { Tooltip } from 'antd';
import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
import './index.less';

interface EllipsisTextProps {
  text: string | number;
  lines?: number;
  width?: number | string;
  showTooltip?: boolean;
  style?: React.CSSProperties;
  className?: string;
}

const EllipsisText: React.FC<EllipsisTextProps> = ({
  text,
  lines = 1,
  width = '100%',
  showTooltip = true,
  style = {},
  className,
}) => {
  const textRef = useRef<HTMLSpanElement>(null);
  const [isOverflow, setIsOverflow] = useState(false);

  const checkOverflow = () => {
    const el = textRef.current;
    if (!el) return;
    setIsOverflow(el.scrollHeight > el.clientHeight + 2); // 防浮点误差
  };

  useEffect(() => {
    checkOverflow();
    const observer = new ResizeObserver(() => checkOverflow());
    if (textRef.current) observer.observe(textRef.current);
    return () => observer.disconnect();
  }, [text, width, lines]);

  const content = (
    <span
      ref={textRef}
      className={classNames('ellipsis-text', className)}
      style={{
        WebkitLineClamp: lines,
        width,
        ...style,
      }}
    >
      {text}
    </span>
  );

  return showTooltip && isOverflow ? (
    <Tooltip title={text}>{content}</Tooltip>
  ) : (
    content
  );
};

export default EllipsisText;

2️⃣ EllipsisText.less(多行省略样式)

arduino 复制代码
.ellipsis-text {
  display: -webkit-box;         // 多行省略必需
  -webkit-box-orient: vertical; // 设置伸展方向
  overflow: hidden;             // 隐藏溢出文本
  text-overflow: ellipsis;      // 溢出显示省略号
  word-break: break-word;       // 防止长单词撑破容器
  width: 100%;                  // 自适应父元素宽度
}

3️⃣ ProTable.tsx(封装 Table)

ini 复制代码
import { EllipsisText } from '@pl/react-ui';
import { Table } from 'antd';
import type { ColumnsType, ColumnType, TableProps } from 'antd/es/table';
import React, { useMemo } from 'react';

interface CustomEllipsis {
  lines?: number;
  showTooltip?: boolean;
  style?: React.CSSProperties;
  className?: string;
}

interface ProColumnType<T> extends ColumnType<T> {
  customEllipsis?: CustomEllipsis;
}

type ProTableProps<T> = TableProps<T> & {
  columns: ProColumnType<T>[];
};

function ProTable<T extends object>({ columns, ...rest }: ProTableProps<T>) {
  const enhancedColumns = useMemo(() => {
    return columns.map((col: ProColumnType<T>) => {
      if (!col.customEllipsis) return col;

      const {
        lines = 1,
        showTooltip = true,
        style = {},
        className,
      } = col.customEllipsis;
      const originalRender = col.render;

      return {
        ...col,
        render: (text: any, record: T, index: number) => {
          const content = originalRender
            ? originalRender(text, record, index)
            : text;
          return (
            <EllipsisText
              text={content}
              lines={lines}
              showTooltip={showTooltip}
              width={col.width}
              style={style}
              className={className}
            />
          );
        },
      };
    });
  }, [columns]);

  return <Table {...rest} columns={enhancedColumns as ColumnsType<T>} />;
}

export default ProTable;

4️⃣ Demo 使用示例

typescript 复制代码
import { ProTable } from '@pl/react-ui';
import React from 'react';
interface DataType {
  key: string;
  name: string;
  description: string;
  extra: string;
}

const data: DataType[] = [
  {
    key: '1',
    name: 'Ant Design Table Component',
    description:
      '这是一个可以多行省略的示例文字,如果内容太长,会显示省略号,并通过 Tooltip 展示完整内容。',
    extra: '这是额外信息,可以自定义 render。',
  },
  {
    key: '2',
    name: 'Another Row',
    description: '短文字不需要省略。',
    extra: '短信息',
  },
];

const columns = [
  {
    title: 'Name(1行省略 + 显示Tooltip)',
    dataIndex: 'name',
    key: 'name',
    customEllipsis: { lines: 1, showTooltip: true },
  },
  {
    title: 'Description(2行省略 + 显示Tooltip)',
    dataIndex: 'description',
    key: 'description',
    customEllipsis: { lines: 2, showTooltip: true },
  },
  {
    title: 'Extra Info(1行省略 + 不显示Tooltip)',
    dataIndex: 'extra',
    key: 'extra',
    customEllipsis: {
      lines: 1,
      showTooltip: false,
      style: { background: 'pink' },
      className: 'extra-class',
    },
    render: (text: string) => <span style={{ color: 'blue' }}>{text}</span>,
  },
];

export default function Demo() {
  return (
    <ProTable<DataType>
      columns={columns}
      dataSource={data}
      pagination={false}
      bordered
    />
  );
}

✅ 特性总结

  1. 多行文字省略,可自定义行数
  2. 动态溢出检测,自动显示 Tooltip
  3. 自定义样式和类名,可满足企业级表格需求
  4. 兼容自定义 render,保持原列功能
相关推荐
王夏奇1 分钟前
python中的__all__ 具体用法
java·前端·python
大家的林语冰42 分钟前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong231 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
田八1 小时前
聊聊AI的发展史,AI的爆发并不是偶然
前端·人工智能·程序员
zhanghongbin011 小时前
AI 采集器:Claude Code、OpenAI、LiteLLM 监控
java·前端·人工智能
IT_陈寒1 小时前
Python的列表推导式里藏了个坑,差点让我加班到凌晨
前端·人工智能·后端
吴声子夜歌1 小时前
ES6——正则的扩展详解
前端·mysql·es6
天***88522 小时前
Edge 浏览器离线绿色增强版+官方安装包,支持win7等系统
前端·edge
漫游的渔夫2 小时前
别再直接 `json.loads` 了!AI 返回的 JSON 坑位指南
前端·人工智能
软件工程师文艺2 小时前
从0到1:Claude Code如何用React构建CLI应用
前端·react.js·前端框架