在 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,保持原列功能
相关推荐
优秀员工不受影响6 小时前
如何使用 Volta
前端
my一阁6 小时前
tomcat web实测
java·前端·nginx·tomcat·负载均衡
huangql5206 小时前
前端多版本零404部署实践:为什么会404,以及怎么彻底解决
前端
梵得儿SHI6 小时前
Vue 数据绑定深入浅出:从 v-bind 到 v-model 的实战指南
前端·javascript·vue.js·双向绑定·vue 数据绑定机制·单向绑定·v-bind v-model
Moment6 小时前
Electron 发布 39 版本 ,这更新速度也变态了吧❓︎❓︎❓︎
前端·javascript·node.js
消失的旧时光-19436 小时前
8方向控制圆盘View
android·前端
自由日记6 小时前
前端学习:选择器的类别
前端·javascript·学习
念念不忘 必有回响6 小时前
Nginx前端配置与服务器部署详解
服务器·前端·nginx