Table 表格 #

概述 #

Table 表格是展示数据的核心组件,支持分页、排序、筛选、选择等功能,是企业级应用中最常用的组件之一。

基础用法 #

基本表格 #

tsx
import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  { title: '年龄', dataIndex: 'age', key: 'age' },
  { title: '地址', dataIndex: 'address', key: 'address' },
];

const data = [
  { key: '1', name: '张三', age: 32, address: '北京市朝阳区' },
  { key: '2', name: '李四', age: 42, address: '上海市浦东新区' },
  { key: '3', name: '王五', age: 28, address: '广州市天河区' },
];

<Table columns={columns} dataSource={data} />

带边框表格 #

tsx
import { Table } from 'antd';

<Table columns={columns} dataSource={data} bordered />

加载状态 #

tsx
import { Table } from 'antd';

<Table columns={columns} dataSource={data} loading />

可展开表格 #

tsx
import { Table } from 'antd';

<Table
  columns={columns}
  dataSource={data}
  expandable={{
    expandedRowRender: (record) => (
      <p style={{ margin: 0 }}>{record.description}</p>
    ),
    rowExpandable: (record) => record.name !== 'Not Expandable',
  }}
/>

分页 #

基本分页 #

tsx
import { Table } from 'antd';

<Table
  columns={columns}
  dataSource={data}
  pagination={{ pageSize: 10 }}
/>

分页配置 #

tsx
import { Table } from 'antd';

<Table
  columns={columns}
  dataSource={data}
  pagination={{
    current: 1,
    pageSize: 10,
    total: 100,
    showSizeChanger: true,
    showQuickJumper: true,
    showTotal: (total) => `共 ${total} 条`,
  }}
/>

服务端分页 #

tsx
import { Table } from 'antd';
import { useState, useEffect } from 'react';

const App = () => {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [pagination, setPagination] = useState({
    current: 1,
    pageSize: 10,
    total: 0,
  });

  const fetchData = async (params = {}) => {
    setLoading(true);
    const result = await fetch(`/api/users?${new URLSearchParams(params)}`);
    setData(result.data);
    setPagination({
      ...pagination,
      total: result.total,
    });
    setLoading(false);
  };

  const handleTableChange = (pagination) => {
    fetchData({
      page: pagination.current,
      pageSize: pagination.pageSize,
    });
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <Table
      columns={columns}
      dataSource={data}
      loading={loading}
      pagination={pagination}
      onChange={handleTableChange}
    />
  );
};

排序 #

本地排序 #

tsx
import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
    sorter: (a, b) => a.age - b.age,
  },
  {
    title: '地址',
    dataIndex: 'address',
    key: 'address',
    sorter: (a, b) => a.address.localeCompare(b.address),
  },
];

<Table columns={columns} dataSource={data} />

远程排序 #

tsx
import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
    sorter: true,
  },
];

const handleTableChange = (pagination, filters, sorter) => {
  fetchData({
    sortField: sorter.field,
    sortOrder: sorter.order,
  });
};

<Table
  columns={columns}
  dataSource={data}
  onChange={handleTableChange}
/>

筛选 #

本地筛选 #

tsx
import { Table } from 'antd';

const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    filters: [
      { text: '张三', value: '张三' },
      { text: '李四', value: '李四' },
    ],
    onFilter: (value, record) => record.name.includes(value),
  },
  {
    title: '年龄',
    dataIndex: 'age',
    key: 'age',
    sorter: (a, b) => a.age - b.age,
  },
];

<Table columns={columns} dataSource={data} />

远程筛选 #

tsx
import { Table } from 'antd';

const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    filters: [
      { text: '张三', value: '张三' },
      { text: '李四', value: '李四' },
    ],
  },
];

const handleTableChange = (pagination, filters) => {
  fetchData({
    name: filters.name,
  });
};

<Table
  columns={columns}
  dataSource={data}
  onChange={handleTableChange}
/>

选择 #

复选框选择 #

tsx
import { Table } from 'antd';
import { useState } from 'react';

const [selectedRowKeys, setSelectedRowKeys] = useState([]);

const rowSelection = {
  selectedRowKeys,
  onChange: (keys) => setSelectedRowKeys(keys),
};

<Table
  rowSelection={rowSelection}
  columns={columns}
  dataSource={data}
/>

单选 #

tsx
import { Table } from 'antd';

const rowSelection = {
  type: 'radio',
  onChange: (selectedRowKeys, selectedRows) => {
    console.log(selectedRows);
  },
};

<Table
  rowSelection={rowSelection}
  columns={columns}
  dataSource={data}
/>

自定义选择 #

tsx
import { Table } from 'antd';

const rowSelection = {
  selections: [
    Table.SELECTION_ALL,
    Table.SELECTION_INVERT,
    Table.SELECTION_NONE,
    {
      key: 'odd',
      text: '选择奇数行',
      onSelect: (changeableRowKeys) => {
        let newSelectedRowKeys = [];
        newSelectedRowKeys = changeableRowKeys.filter((_, index) => {
          if (index % 2 !== 0) {
            return false;
          }
          return true;
        });
        setSelectedRowKeys(newSelectedRowKeys);
      },
    },
  ],
};

<Table
  rowSelection={rowSelection}
  columns={columns}
  dataSource={data}
/>

固定列 #

左侧固定 #

tsx
import { Table } from 'antd';

const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    fixed: 'left',
    width: 100,
  },
  { title: '年龄', dataIndex: 'age', key: 'age', width: 100 },
  { title: '地址', dataIndex: 'address', key: 'address' },
];

<Table columns={columns} dataSource={data} scroll={{ x: 1300 }} />

右侧固定 #

tsx
import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  { title: '年龄', dataIndex: 'age', key: 'age' },
  {
    title: '操作',
    key: 'action',
    fixed: 'right',
    width: 100,
    render: () => <a>删除</a>,
  },
];

<Table columns={columns} dataSource={data} scroll={{ x: 1300 }} />

固定表头 #

tsx
import { Table } from 'antd';

<Table
  columns={columns}
  dataSource={data}
  scroll={{ y: 400 }}
/>

可编辑表格 #

tsx
import { Table, Input, Form } from 'antd';
import { useState } from 'react';

const EditableCell = ({
  editing,
  dataIndex,
  title,
  record,
  children,
  ...restProps
}) => {
  return (
    <td {...restProps}>
      {editing ? (
        <Form.Item
          name={dataIndex}
          style={{ margin: 0 }}
          rules={[{ required: true, message: `请输入${title}` }]}
        >
          <Input />
        </Form.Item>
      ) : (
        children
      )}
    </td>
  );
};

const App = () => {
  const [form] = Form.useForm();
  const [editingKey, setEditingKey] = useState('');

  const isEditing = (record) => record.key === editingKey;

  const edit = (record) => {
    form.setFieldsValue({ ...record });
    setEditingKey(record.key);
  };

  const columns = [
    { title: '姓名', dataIndex: 'name', key: 'name', editable: true },
    { title: '年龄', dataIndex: 'age', key: 'age', editable: true },
    {
      title: '操作',
      dataIndex: 'operation',
      render: (_, record) => {
        const editable = isEditing(record);
        return editable ? (
          <span>
            <a onClick={() => save(record.key)}>保存</a>
            <a onClick={() => cancel()}>取消</a>
          </span>
        ) : (
          <a disabled={editingKey !== ''} onClick={() => edit(record)}>
            编辑
          </a>
        );
      },
    },
  ];

  const mergedColumns = columns.map((col) => {
    if (!col.editable) {
      return col;
    }
    return {
      ...col,
      onCell: (record) => ({
        record,
        dataIndex: col.dataIndex,
        title: col.title,
        editing: isEditing(record),
      }),
    };
  });

  return (
    <Form form={form} component={false}>
      <Table
        components={{
          body: {
            cell: EditableCell,
          },
        }}
        columns={mergedColumns}
        dataSource={data}
      />
    </Form>
  );
};

API #

Table #

属性 说明 类型 默认值
bordered 是否显示边框 boolean false
columns 表格列配置 ColumnType[] -
dataSource 数据源 object[] -
expandable 展开配置 expandable -
footer 表格尾部 () => ReactNode -
loading 加载状态 boolean | SpinProps false
locale 国际化配置 object -
pagination 分页配置 PaginationConfig | false -
rowClassName 行类名 (record, index) => string -
rowKey 行 key string | (record) => string key
rowSelection 选择配置 RowSelection -
scroll 滚动配置 -
showHeader 是否显示表头 boolean true
showSorterTooltip 排序提示 boolean true
size 表格大小 default | middle | small default
sortDirections 排序方向 (ascend | descend)[] -
sticky 粘性头部 boolean | Sticky -
summary 总结栏 (currentData) => ReactNode -
tableLayout 表格布局 auto | fixed -
title 表格标题 () => ReactNode -
onChange 分页排序筛选变化回调 (pagination, filters, sorter, extra) => void -
onHeaderRow 表头行属性 (columns, index) => object -
onRow 行属性 (record, index) => object -

Column #

属性 说明 类型 默认值
align 对齐方式 left | right | center left
className 列类名 string -
colSpan 合并列 number -
dataIndex 数据字段名 string -
ellipsis 超出省略 boolean | false
filters 筛选菜单 { text, value }[] -
filterDropdown 自定义筛选 ReactNode -
filterDropdownProps 筛选菜单属性 object -
filterMultiple 是否多选 boolean true
filterSearch 筛选搜索 boolean | function false
fixed 固定列 left | right -
key React key string -
render 渲染函数 (text, record, index) => ReactNode -
responsive 响应式 Breakpoint[] -
rowScope 行作用域 row | col -
shouldCellUpdate 单元格更新 (record, prevRecord) => boolean -
showSorterTooltip 排序提示 boolean | TooltipProps -
sortDirections 排序方向 (ascend | descend)[] -
sorter 排序函数 boolean | function -
sortOrder 排序状态 ascend | descend -
title 列标题 ReactNode -
width 列宽度 string | number -
onCell 单元格属性 (record, index) => object -
onFilter 筛选函数 (value, record) => boolean -
onFilterDropdownOpenChange 筛选菜单展开回调 (visible) => void -
onHeaderCell 表头单元格属性 (column) => object -

最佳实践 #

1. 性能优化 #

tsx
import { Table } from 'antd';
import { useMemo } from 'react';

const columns = useMemo(() => [
  { title: '姓名', dataIndex: 'name' },
  { title: '年龄', dataIndex: 'age' },
], []);

<Table columns={columns} dataSource={data} />

2. 虚拟滚动 #

tsx
import { Table } from 'antd';

<Table
  virtual
  scroll={{ x: 2000, y: 500 }}
  columns={columns}
  dataSource={largeData}
/>

3. 处理大数据 #

tsx
import { Table } from 'antd';

<Table
  columns={columns}
  dataSource={data}
  pagination={{
    pageSize: 20,
    showSizeChanger: true,
  }}
  scroll={{ y: 500 }}
/>

下一步 #

接下来学习 List 列表 组件!

最后更新:2026-03-28