在 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,保持原列功能
相关推荐
心在飞扬3 分钟前
RAPTOR 递归文档树优化策略
前端·后端
前端Hardy20 分钟前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy22 分钟前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js
青青家的小灰灰27 分钟前
从入门到精通:Vue3 ref vs reactive 最佳实践与底层原理
前端·vue.js·面试
OpenTiny社区38 分钟前
我的新同事是个AI:支持skill后,它用TinyVue搭项目还挺溜!
前端·vue.js·ai编程
心在飞扬1 小时前
MultiVector 多向量检索
前端·后端
用户39051332192881 小时前
async 函数返回的 Promise 状态何时变为 resolved
前端
李剑一1 小时前
大屏天气展示太普通?视觉升级!用 Canvas 做动态天气遮罩,雷阵雨效果直接封神
前端·vue.js·canvas
Lee川1 小时前
现代Web开发中的CSS继承、Flexbox布局与LocalStorage交互:从文档解析到实践应用
前端·css
炫饭第一名1 小时前
速通Canvas指北🦮——图形、文本与样式篇
前端·javascript·程序员