Table 表格

展示行列数据。

何时使用#

  • 当有大量结构化的数据需要展现时;
  • 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。

如何使用#

指定表格的数据源 dataSource 为一个数组。

const dataSource = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}];

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

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

注:dataSource0.11.0 版本后不再支持远程模式。

代码演示

姓名年龄住址操作
胡彦斌32西湖区湖底公园1号操作一胡彦斌操作二更多
胡彦祖42西湖区湖底公园1号操作一胡彦祖操作二更多
李大嘴32西湖区湖底公园1号操作一李大嘴操作二更多

简单的表格,最后一列是各种操作。

import { Table, Icon } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  key: 'name',
  render(text) {
    return <a href="#">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age',
  key: 'age',
}, {
  title: '住址',
  dataIndex: 'address',
  key: 'address',
}, {
  title: '操作',
  key: 'operation',
  render(text, record) {
    return (
      <span>
        <a href="#">操作一{record.name}</a>
        <span className="ant-divider"></span>
        <a href="#">操作二</a>
        <span className="ant-divider"></span>
        <a href="#" className="ant-dropdown-link">
          更多 <Icon type="down" />
        </a>
      </span>
    );
  }
}];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

ReactDOM.render(<Table columns={columns} dataSource={data} />
, mountNode);
姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

第一列是联动的选择框。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  render(text) {
    return <a href="#">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

// 通过 rowSelection 对象表明需要行选择
const rowSelection = {
  onChange(selectedRowKeys, selectedRows) {
    console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  },
  onSelect(record, selected, selectedRows) {
    console.log(record, selected, selectedRows);
  },
  onSelectAll(selected, selectedRows, changeRows) {
    console.log(selected, selectedRows, changeRows);
  },
};

ReactDOM.render(<Table rowSelection={rowSelection} columns={columns} dataSource={data} />
, mountNode);
姓名年龄住址
李大嘴032西湖区湖底公园0号
李大嘴132西湖区湖底公园1号
李大嘴232西湖区湖底公园2号
李大嘴332西湖区湖底公园3号
李大嘴432西湖区湖底公园4号
李大嘴532西湖区湖底公园5号
李大嘴632西湖区湖底公园6号
李大嘴732西湖区湖底公园7号
李大嘴832西湖区湖底公园8号
李大嘴932西湖区湖底公园9号

选择后进行操作,完成后清空选择,通过 rowSelection.selectedRowKeys 来控制选中项。

import { Table, Button } from 'antd';

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

const data = [];
for (let i = 0; i < 46; i++) {
  data.push({
    key: i,
    name: `李大嘴${i}`,
    age: 32,
    address: `西湖区湖底公园${i}号`
  });
}

const App = React.createClass({
  getInitialState() {
    return {
      selectedRowKeys: [],  // 这里配置默认勾选列
      loading: false,
    };
  },
  start() {
    this.setState({ loading: true });
    // 模拟 ajax 请求,完成后清空
    setTimeout(() => {
      this.setState({
        selectedRowKeys: [],
        loading: false,
      });
    }, 1000);
  },
  onSelectChange(selectedRowKeys) {
    console.log('selectedRowKeys changed: ', selectedRowKeys);
    this.setState({ selectedRowKeys });
  },
  render() {
    const { loading, selectedRowKeys } = this.state;
    const rowSelection = {
      selectedRowKeys,
      onChange: this.onSelectChange,
    };
    const hasSelected = selectedRowKeys.length > 0;
    return (
      <div>
        <div style={{ marginBottom: 16 }}>
           <Button type="primary" onClick={this.start}
             disabled={!hasSelected} loading={loading}>操作</Button>
           <span style={{ marginLeft: 8 }}>{hasSelected ? `选择了 ${selectedRowKeys.length} 个对象` : ''}</span>
        </div>
        <Table rowSelection={rowSelection} columns={columns} dataSource={data} />
      </div>
    );
  }
});

ReactDOM.render(<App />, mountNode);
姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

配置选择框的默认属性。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  render: text => <a href="#">{text}</a>,
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

// 通过 rowSelection 对象表明需要行选择
const rowSelection = {
  getCheckboxProps(record) {
    return {
      disabled: record.name === '胡彦祖'    // 配置无法勾选的列
    };
  },
};

ReactDOM.render(<Table rowSelection={rowSelection} columns={columns} dataSource={data} />
, mountNode);
姓名年龄住址
李大嘴032西湖区湖底公园0号
李大嘴132西湖区湖底公园1号
李大嘴232西湖区湖底公园2号
李大嘴332西湖区湖底公园3号
李大嘴432西湖区湖底公园4号
李大嘴532西湖区湖底公园5号
李大嘴632西湖区湖底公园6号
李大嘴732西湖区湖底公园7号
李大嘴832西湖区湖底公园8号
李大嘴932西湖区湖底公园9号

数据项较多时显示分页。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  render(text) {
    return <a href="#">{text}</a>;
  }
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];

const data = [];
for (let i = 0; i < 46; i++) {
  data.push({
    key: i,
    name: `李大嘴${i}`,
    age: 32,
    address: `西湖区湖底公园${i}号`
  });
}

const pagination = {
  total: data.length,
  showSizeChanger: true,
  onShowSizeChange(current, pageSize) {
    console.log('Current: ', current, '; PageSize: ', pageSize);
  },
  onChange(current) {
    console.log('Current: ', current);
  }
};

ReactDOM.render(<Table columns={columns} dataSource={data} pagination={pagination} />
, mountNode);
姓名
年龄
地址
胡斌32南湖区湖底公园1号
胡彦祖42西湖区湖底公园12号
李大嘴32南湖区湖底公园123号
李秀莲大嘴哥32西湖区湖底公园123号

对某一列数据进行筛选,使用列的 filter 属性来指定需要筛选菜单的列,onFilter 用于筛选当前数据,filterMultiple 用于指定多选和单选。

对某一列数据进行排序,通过指定列的 sorter 函数即可启动排序按钮。sorter: function(a, b) { ... }, a、b 为比较的两个列数据。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  filters: [{
    text: '姓李的',
    value: '李',
  }, {
    text: '姓胡的',
    value: '胡',
  }, {
    text: '子菜单',
    value: '子菜单',
    children: [{
      text: '姓陈的',
      value: '陈',
    }, {
      text: '姓王的',
      value: '王',
    }],
  }],
  // 指定确定筛选的条件函数
  // 这里是名字中第一个字是 value
  onFilter: (value, record) => record.name.indexOf(value) === 0,
  sorter: (a, b) => a.name.length - b.name.length,
}, {
  title: '年龄',
  dataIndex: 'age',
  sorter: (a, b) => a.age - b.age,
}, {
  title: '地址',
  dataIndex: 'address',
  filters: [{
    text: '南湖',
    value: '南湖',
  }, {
    text: '西湖',
    value: '西湖',
  }],
  filterMultiple: false,
  onFilter: (value, record) => record.address.indexOf(value) === 0,
  sorter: (a, b) => a.address.length - b.address.length,
}];

const data = [{
  key: '1',
  name: '胡斌',
  age: 32,
  address: '南湖区湖底公园1号',
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园12号',
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '南湖区湖底公园123号',
}, {
  key: '4',
  name: '李秀莲大嘴哥',
  age: 32,
  address: '西湖区湖底公园123号',
}];

function onChange(pagination, filters, sorter) {
  // 点击分页、筛选、排序时触发
  console.log('各类参数是', pagination, filters, sorter);
}

ReactDOM.render(<Table columns={columns} dataSource={data} onChange={onChange} />, mountNode);
姓名年龄
住址
胡彦斌ajax132西湖区湖底公园1号
胡彦祖ajax242西湖区湖底公园1号
李大嘴ajax332西湖区湖底公园1号
李大嘴ajax432西湖区湖底公园1号
李大嘴ajax532西湖区湖底公园1号
李大嘴ajax632西湖区湖底公园1号
李大嘴ajax732西湖区湖底公园1号
李大嘴ajax832西湖区湖底公园1号
李大嘴ajax932西湖区湖底公园1号
李大嘴ajax1032西湖区湖底公园1号

0.11.0 以后,dataSource 远程模式被移除,用户可以自行实现数据读取方式。

这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。

另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 onFiltersorter 函数,而是在把筛选和排序的参数发到服务端来处理。

注意,此示例是静态数据模拟,展示数据不会变化,请打开网络面板查看请求。

import { Table } from 'antd';
import reqwest from 'reqwest';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  filters: [
    { text: '姓李的', value: '李' },
    { text: '姓胡的', value: '胡' },
  ],
}, {
  title: '年龄',
  dataIndex: 'age',
  sorter: true,
}, {
  title: '住址',
  dataIndex: 'address',
}];

const Test = React.createClass({
  getInitialState() {
    return {
      data: [],
      pagination: {},
      loading: false,
    };
  },
  handleTableChange(pagination, filters, sorter) {
    const pager = this.state.pagination;
    pager.current = pagination.current;
    this.setState({
      pagination: pager,
    });
    this.fetch({
      pageSize: pagination.pageSize,
      currentPage: pagination.current,
      sortField: sorter.field,
      sortOrder: sorter.order,
      ...filters,
    });
  },
  fetch(params = {}) {
    console.log('请求参数:', params);
    this.setState({ loading: true });
    reqwest({
      url: 'demo/data.json',
      method: 'get',
      data: params,
      type: 'json',
      success: (result) => {
        const pagination = this.state.pagination;
        pagination.total = result.totalCount;
        this.setState({
          loading: false,
          data: result.data,
          pagination,
        });
      }
    });
  },
  componentDidMount() {
    this.fetch();
  },
  render() {
    return (
      <Table columns={columns}
        dataSource={this.state.data}
        pagination={this.state.pagination}
        loading={this.state.loading}
        onChange={this.handleTableChange} />
    );
  }
});

ReactDOM.render(<Test />, mountNode);
姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

传入 pagination 为 false 即可。此时表格将完整显示 dataSource 内的数据,不进行任何分页。

import { Table } from 'antd';

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

const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

ReactDOM.render(<Table columns={columns} dataSource={data} pagination={false} />
, mountNode);

中号表格(紧凑型)

姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

小号表格

姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

紧凑型的列表, 中型列表用于需要数据紧凑展示的情况,小型列表只用于对话框内。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name'
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

ReactDOM.render(<div>
  <h4>中号表格(紧凑型)</h4>
  <Table columns={columns} dataSource={data} size="middle" />
  <h4>小号表格</h4>
  <Table columns={columns} dataSource={data} size="small" />
</div>, mountNode);
姓名资产住址
胡彦斌¥300,000.00西湖区湖底公园1号
胡彦祖¥1,256,000.00西湖区湖底公园1号
李大嘴¥120,000.00西湖区湖底公园1号

添加表格边框线,bordered

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  render(text) {
    return <a href="#">{text}</a>;
  }
}, {
  title: '资产',
  className: 'column-money',
  dataIndex: 'money'
}, {
  title: '住址',
  dataIndex: 'address'
}];

const data = [{
  key: '1',
  name: '胡彦斌',
  money: '¥300,000.00',
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  money: '¥1,256,000.00',
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  money: '¥120,000.00',
  address: '西湖区湖底公园1号'
}];

ReactDOM.render(<Table columns={columns} dataSource={data} bordered />
, mountNode);
.column-money {
  text-align: right;
}
姓名年龄住址操作
胡彦斌32西湖区湖底公园1号删除
吴彦祖42西湖区湖底公园2号删除
李大嘴32西湖区湖底公园3号删除

当表格内容较多不能一次性完全展示时。

import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  { title: '年龄', dataIndex: 'age', key: 'age' },
  { title: '住址', dataIndex: 'address', key: 'address' },
  { title: '操作', dataIndex: '', key: 'x', render: () => <a href="#">删除</a> }
];

const data = [
  { key: 1, name: '胡彦斌', age: 32, address: '西湖区湖底公园1号', description: '我是胡彦斌,今年32岁,住在西湖区湖底公园1号。' },
  { key: 2, name: '吴彦祖', age: 42, address: '西湖区湖底公园2号', description: '我是吴彦祖,今年42岁,住在西湖区湖底公园2号。' },
  { key: 3, name: '李大嘴', age: 32, address: '西湖区湖底公园3号', description: '我是李大嘴,今年32岁,住在西湖区湖底公园3号。' }
];

ReactDOM.render(
<Table columns={columns}
  expandedRowRender={record => <p>{record.description}</p>}
  dataSource={data}
  className="table" />
, mountNode);
姓名年龄家庭电话住址
胡彦斌320571-2209890918889898989西湖区湖底公园1号
胡彦祖420571-2209833318889898888西湖区湖底公园1号
李大嘴320575-2209890918900010002西湖区湖底公园1号
李夫人1818900010002西湖区湖底公园1号
习大大

表头只支持列合并,使用 column 里的 colSpan 进行设置。

表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。

import { Table } from 'antd';

// 事例表中第四行合并了五列,除了第一列设置 colSpan = 5 外
// 其他列的第四行 colSpan = 0 (被合并掉,不会渲染)
const renderContent = function (value, row, index) {
  let obj = {
    children: value,
    props: {}
  };
  if (index === 4) {
    obj.props.colSpan = 0;
  }
  return obj;
};

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  render(text, row, index) {
    if (index < 4) {
      return <a href="#">{text}</a>;
    }
    return {
      children: <a href="#">{text}</a>,
      props: {
        colSpan: 5
      }
    };
  }
}, {
  title: '年龄',
  dataIndex: 'age',
  render: renderContent
}, {
  title: '家庭电话',
  colSpan: 2,
  dataIndex: 'tel',
  render(value, row, index) {
    let obj = {
      children: value,
      props: {}
    };
    // 第三列的第三行行合并
    if (index === 2) {
      obj.props.rowSpan = 2;
    }

    // 第三列的第四行被合并没了,设置 rowSpan = 0 直接不用渲染
    if (index === 3) {
      obj.props.rowSpan = 0;
    }

    if (index === 4) {
      obj.props.colSpan = 0;
    }
    return obj;
  }
}, {
  title: '手机号',
  colSpan: 0,
  dataIndex: 'phone',
  render: renderContent
}, {
  title: '住址',
  dataIndex: 'address',
  render: renderContent
}];

const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  tel: '0571-22098909',
  phone: 18889898989,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  tel: '0571-22098333',
  phone: 18889898888,
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  tel: '0575-22098909',
  phone: 18900010002,
  address: '西湖区湖底公园1号'
}, {
  key: '4',
  name: '李夫人',
  age: 18,
  tel: '0575-22098909',
  phone: 18900010002,
  address: '西湖区湖底公园1号'
}, {
  key: '5',
  name: '习大大',
  age: 18,
  tel: '0575-22098909',
  phone: 18900010002,
  address: '西湖区湖底公园1号'
}];

ReactDOM.render(<Table columns={columns} dataSource={data} bordered />
, mountNode);
姓名年龄住址
胡彦斌32西湖区湖底公园1号
胡彦祖42西湖区湖底公园1号
李大嘴32西湖区湖底公园1号

用属性 loading 控制表格加载中状态。

import { Table, Button } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name'
}, {
  title: '年龄',
  dataIndex: 'age'
}, {
  title: '住址',
  dataIndex: 'address'
}];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
  address: '西湖区湖底公园1号'
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
  address: '西湖区湖底公园1号'
}, {
  key: '3',
  name: '李大嘴',
  age: 32,
  address: '西湖区湖底公园1号'
}];

const App = React.createClass({
  getInitialState() {
    return {
      loading: false
    };
  },
  toggleLoading() {
    this.setState({
      loading: !this.state.loading
    });
  },
  render() {
    return (
      <div>
        <Table columns={columns} dataSource={data} loading={this.state.loading} />
        <Button type="primary" onClick={this.toggleLoading}>切换 loading 状态</Button>
      </div>
    );
  }
});

ReactDOM.render(<App />, mountNode);
姓名年龄住址
李大嘴032西湖区湖底公园0号
李大嘴132西湖区湖底公园1号
李大嘴232西湖区湖底公园2号
李大嘴332西湖区湖底公园3号
李大嘴432西湖区湖底公园4号
李大嘴532西湖区湖底公园5号
李大嘴632西湖区湖底公园6号
李大嘴732西湖区湖底公园7号
李大嘴832西湖区湖底公园8号
李大嘴932西湖区湖底公园9号
李大嘴1032西湖区湖底公园10号
李大嘴1132西湖区湖底公园11号
李大嘴1232西湖区湖底公园12号
李大嘴1332西湖区湖底公园13号
李大嘴1432西湖区湖底公园14号
李大嘴1532西湖区湖底公园15号
李大嘴1632西湖区湖底公园16号
李大嘴1732西湖区湖底公园17号
李大嘴1832西湖区湖底公园18号
李大嘴1932西湖区湖底公园19号
李大嘴2032西湖区湖底公园20号
李大嘴2132西湖区湖底公园21号
李大嘴2232西湖区湖底公园22号
李大嘴2332西湖区湖底公园23号
李大嘴2432西湖区湖底公园24号
李大嘴2532西湖区湖底公园25号
李大嘴2632西湖区湖底公园26号
李大嘴2732西湖区湖底公园27号
李大嘴2832西湖区湖底公园28号
李大嘴2932西湖区湖底公园29号
李大嘴3032西湖区湖底公园30号
李大嘴3132西湖区湖底公园31号
李大嘴3232西湖区湖底公园32号
李大嘴3332西湖区湖底公园33号
李大嘴3432西湖区湖底公园34号
李大嘴3532西湖区湖底公园35号
李大嘴3632西湖区湖底公园36号
李大嘴3732西湖区湖底公园37号
李大嘴3832西湖区湖底公园38号
李大嘴3932西湖区湖底公园39号
李大嘴4032西湖区湖底公园40号
李大嘴4132西湖区湖底公园41号
李大嘴4232西湖区湖底公园42号
李大嘴4332西湖区湖底公园43号
李大嘴4432西湖区湖底公园44号
李大嘴4532西湖区湖底公园45号
李大嘴4632西湖区湖底公园46号
李大嘴4732西湖区湖底公园47号
李大嘴4832西湖区湖底公园48号
李大嘴4932西湖区湖底公园49号

方便一页内展示大量数据。

需要指定 column 的 width 属性,否则列头和内容可能不对齐。

import { Table } from 'antd';

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

const data = [];
for (let i = 0; i < 100; i++) {
  data.push({
    key: i,
    name: `李大嘴${i}`,
    age: 32,
    address: `西湖区湖底公园${i}号`
  });
}

ReactDOM.render(
  <Table columns={columns} dataSource={data} pagination={{ pageSize: 50 }} useFixedHeader />
, mountNode);
姓名年龄列1列2列3列4列5列6列7列8操作
胡彦斌323232323232323232操作
胡彦祖424242424242424242操作

对于列数很多的数据,可以进行横向的分页,通过切换符切换当前展现的列。

import { Table } from 'antd';

const columns = [
  { title: '姓名', dataIndex: 'name', key: 'name' },
  { title: '年龄', dataIndex: 'age', key: 'age' },
  { title: '列1', dataIndex: 'age', key: '1' },
  { title: '列2', dataIndex: 'age', key: '2' },
  { title: '列3', dataIndex: 'age', key: '3' },
  { title: '列4', dataIndex: 'age', key: '4' },
  { title: '列5', dataIndex: 'age', key: '5' },
  { title: '列6', dataIndex: 'age', key: '6' },
  { title: '列7', dataIndex: 'age', key: '7' },
  { title: '列8', dataIndex: 'age', key: '8' },
  {
    title: '操作',
    key: 'operation',
    render() {
      return <a href="#">操作</a>;
    }
  },
];
const data = [{
  key: '1',
  name: '胡彦斌',
  age: 32,
}, {
  key: '2',
  name: '胡彦祖',
  age: 42,
}];

const App = React.createClass({
  render() {
    return <Table columns={columns} dataSource={data} columnsPageRange={[2, 9]} columnsPageSize={4} />;
  }
});

ReactDOM.render(<App />, mountNode);
姓名年龄住址
a32我是a
b32我是b

表格支持树形数据的展示,可以通过设置 indentSize 以控制每一层的缩进宽度。

注:暂不支持父子数据递归关联选择。

import { Table } from 'antd';

const columns = [{
  title: '姓名',
  dataIndex: 'name',
  key: 'name',
  width: '40%',
}, {
  title: '年龄',
  dataIndex: 'age',
  key: 'age',
  width: '30%',
}, {
  title: '住址',
  dataIndex: 'address',
  key: 'address',
  width: '30%',
}];

const data = [{
  key: 1,
  name: 'a',
  age: 32,
  address: '我是a',
  children: [{
    key: 11,
    name: 'aa',
    age: 33,
    address: '我是aa',
  }, {
    key: 12,
    name: 'ab',
    age: 33,
    address: '我是ab',
    children: [{
      key: 121,
      name: 'aba',
      age: 33,
      address: '我是aba',
    }],
  }, {
    key: 13,
    name: 'ac',
    age: 33,
    address: '我是ac',
    children: [{
      key: 131,
      name: 'aca',
      age: 33,
      address: '我是aca',
      children: [{
        key: 1311,
        name: 'acaa',
        age: 33,
        address: '我是acaa',
      }, {
        key: 1312,
        name: 'acab',
        age: 33,
        address: '我是acab',
      }],
    }],
  }],
}, {
  key: 2,
  name: 'b',
  age: 32,
  address: '我是b',
}];

// 通过 rowSelection 对象表明需要行选择
const rowSelection = {
  onChange(selectedRowKeys, selectedRows) {
    console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  },
  onSelect(record, selected, selectedRows) {
    console.log(record, selected, selectedRows);
  },
  onSelectAll(selected, selectedRows, changeRows) {
    console.log(selected, selectedRows, changeRows);
  }
};

ReactDOM.render(
  <Table columns={columns} rowSelection={rowSelection} dataSource={data} />,
  mountNode
);

API#

Table#

参数 说明 类型 默认值
rowSelection 列表项是否可选择,配置项 Object null
pagination 分页器,配置项参考 pagination,设为 false 时不显示分页 Object
size 正常或迷你类型,default or small String default
dataSource 数据数组 Array
columns 表格列的配置描述,具体项见下表 Array -
rowKey 表格行 key 的取值 Function(record, index):string record.key
rowClassName 表格行的类名 Function(record, index):string -
expandedRowRender 额外的展开行 Function -
defaultExpandedRowKeys 默认展开的行 Array -
onChange 分页、排序、筛选变化时触发 Function(pagination, filters, sorter)
loading 页面是否加载中 Boolean false
locale 默认文案设置,目前包括排序、过滤、空数据文案 Object filterConfirm: '确定'
filterReset: '重置'
emptyText: '暂无数据'
默认值
indentSize 展示树形数据时,每层缩进的宽度,以 px 为单位 Number 15
onRowClick 处理行点击事件 Function(record, index) -
useFixedHeader 是否固定表头 Boolean false
bordered 是否展示外边框和列边框 Boolean false
showHeader 是否显示表头 Boolean true
footer 表格底部自定义渲染函数 Function(currentPageData)

Column#

列描述数据对象,是 columns 中的一项。

参数 说明 类型 默认值
title 列头显示文字 String or React.Element
key React 需要的 key,建议设置 String
dataIndex 列数据在数据项中对应的 key String
render 生成复杂数据的渲染函数,参数分别为当前列的值,当前列数据,列索引,@return里面可以设置表格行/列合并 Function(text, record, index) {}
filters 表头的筛选菜单项 Array
onFilter 本地模式下,确定筛选的运行函数 Function
filterMultiple 是否多选 Boolean true
sorter 排序函数,本地排序使用一个函数,需要服务端排序可设为 true Function or Boolean -
colSpan 表头列合并,设置为 0 时,不渲染 Number
width 列宽度 String or Number -
className 列的 className String -

rowSelection#

选择功能的配置。

参数 说明 类型 默认值
type 多选/单选,checkbox or radio String checkbox
selectedRowKeys 指定选中项的 key 数组,需要和 onChange 进行配合 Array []
onChange 选中项发生变化的时的回调 Function(selectedRowKeys, selectedRows) -
getCheckboxProps 选择框的默认属性配置 Function(record) -
onSelect 用户手动选择/取消选择某列的回调 Function(record, selected, selectedRows) -
onSelectAll 用户手动选择/取消选择所有列的回调 Function(selected, selectedRows, changeRows) -

注意#

按照 React 的规范,所有的组件数组必须绑定 key。在 Table 中,dataSourcecolumns 里的数据值都需要指定 key 值。对于 dataSource 默认将每列数据的 key 属性作为唯一的标识。

如果你的数据没有这个属性,务必使用 rowKey 来指定数据列的主键。若没有指定,控制台会出现以下的提示,表格组件也会出现各类奇怪的错误。

// 比如你的数据主键是 uid
return <Table rowKey={record => record.uid} />;