• Table表格
    • 设计师专属
    • 何时使用
    • 如何使用
    • 代码演示
    • API
      • Table
        • onRow 用法
      • Column
      • ColumnGroup
      • pagination
      • rowSelection
      • selection
    • 在 TypeScript 中使用
    • 注意

    Table表格

    展示行列数据。

    设计师专属

    安装 Kitchen Sketch 插件 ?,两步就可以自动生成 Ant Design 表格组件。

    何时使用

    • 当有大量结构化的数据需要展现时;

    • 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。

    如何使用

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

    1. const dataSource = [
    2. {
    3. key: '1',
    4. name: '胡彦斌',
    5. age: 32,
    6. address: '西湖区湖底公园1号',
    7. },
    8. {
    9. key: '2',
    10. name: '胡彦祖',
    11. age: 42,
    12. address: '西湖区湖底公园1号',
    13. },
    14. ];
    15. const columns = [
    16. {
    17. title: '姓名',
    18. dataIndex: 'name',
    19. key: 'name',
    20. },
    21. {
    22. title: '年龄',
    23. dataIndex: 'age',
    24. key: 'age',
    25. },
    26. {
    27. title: '住址',
    28. dataIndex: 'address',
    29. key: 'address',
    30. },
    31. ];
    32. <Table dataSource={dataSource} columns={columns} />;

    代码演示

    Table 表格 - 图1

    基本用法

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

    1. import { Table, Divider, Tag } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. key: 'name',
    7. render: text => <a href="javascript:;">{text}</a>,
    8. },
    9. {
    10. title: 'Age',
    11. dataIndex: 'age',
    12. key: 'age',
    13. },
    14. {
    15. title: 'Address',
    16. dataIndex: 'address',
    17. key: 'address',
    18. },
    19. {
    20. title: 'Tags',
    21. key: 'tags',
    22. dataIndex: 'tags',
    23. render: tags => (
    24. <span>
    25. {tags.map(tag => {
    26. let color = tag.length > 5 ? 'geekblue' : 'green';
    27. if (tag === 'loser') {
    28. color = 'volcano';
    29. }
    30. return (
    31. <Tag color={color} key={tag}>
    32. {tag.toUpperCase()}
    33. </Tag>
    34. );
    35. })}
    36. </span>
    37. ),
    38. },
    39. {
    40. title: 'Action',
    41. key: 'action',
    42. render: (text, record) => (
    43. <span>
    44. <a href="javascript:;">Invite {record.name}</a>
    45. <Divider type="vertical" />
    46. <a href="javascript:;">Delete</a>
    47. </span>
    48. ),
    49. },
    50. ];
    51. const data = [
    52. {
    53. key: '1',
    54. name: 'John Brown',
    55. age: 32,
    56. address: 'New York No. 1 Lake Park',
    57. tags: ['nice', 'developer'],
    58. },
    59. {
    60. key: '2',
    61. name: 'Jim Green',
    62. age: 42,
    63. address: 'London No. 1 Lake Park',
    64. tags: ['loser'],
    65. },
    66. {
    67. key: '3',
    68. name: 'Joe Black',
    69. age: 32,
    70. address: 'Sidney No. 1 Lake Park',
    71. tags: ['cool', 'teacher'],
    72. },
    73. ];
    74. ReactDOM.render(<Table columns={columns} dataSource={data} />, mountNode);

    Table 表格 - 图2

    JSX 风格的 API

    使用 JSX 风格的 API(2.5.0 以后引入)

    这个只是一个描述 columns 的语法糖,所以你不能用其他组件去包裹 ColumnColumnGroup

    1. import { Table, Divider, Tag } from 'antd';
    2. const { Column, ColumnGroup } = Table;
    3. const data = [
    4. {
    5. key: '1',
    6. firstName: 'John',
    7. lastName: 'Brown',
    8. age: 32,
    9. address: 'New York No. 1 Lake Park',
    10. tags: ['nice', 'developer'],
    11. },
    12. {
    13. key: '2',
    14. firstName: 'Jim',
    15. lastName: 'Green',
    16. age: 42,
    17. address: 'London No. 1 Lake Park',
    18. tags: ['loser'],
    19. },
    20. {
    21. key: '3',
    22. firstName: 'Joe',
    23. lastName: 'Black',
    24. age: 32,
    25. address: 'Sidney No. 1 Lake Park',
    26. tags: ['cool', 'teacher'],
    27. },
    28. ];
    29. ReactDOM.render(
    30. <Table dataSource={data}>
    31. <ColumnGroup title="Name">
    32. <Column title="First Name" dataIndex="firstName" key="firstName" />
    33. <Column title="Last Name" dataIndex="lastName" key="lastName" />
    34. </ColumnGroup>
    35. <Column title="Age" dataIndex="age" key="age" />
    36. <Column title="Address" dataIndex="address" key="address" />
    37. <Column
    38. title="Tags"
    39. dataIndex="tags"
    40. key="tags"
    41. render={tags => (
    42. <span>
    43. {tags.map(tag => (
    44. <Tag color="blue" key={tag}>
    45. {tag}
    46. </Tag>
    47. ))}
    48. </span>
    49. )}
    50. />
    51. <Column
    52. title="Action"
    53. key="action"
    54. render={(text, record) => (
    55. <span>
    56. <a href="javascript:;">Invite {record.lastName}</a>
    57. <Divider type="vertical" />
    58. <a href="javascript:;">Delete</a>
    59. </span>
    60. )}
    61. />
    62. </Table>,
    63. mountNode,
    64. );

    Table 表格 - 图3

    可选择

    第一列是联动的选择框。

    默认点击 checkbox 触发选择行为,需要点击行触发可以参考例子:https://codesandbox.io/s/000vqw38rl

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. render: text => <a href="javascript:;">{text}</a>,
    7. },
    8. {
    9. title: 'Age',
    10. dataIndex: 'age',
    11. },
    12. {
    13. title: 'Address',
    14. dataIndex: 'address',
    15. },
    16. ];
    17. const data = [
    18. {
    19. key: '1',
    20. name: 'John Brown',
    21. age: 32,
    22. address: 'New York No. 1 Lake Park',
    23. },
    24. {
    25. key: '2',
    26. name: 'Jim Green',
    27. age: 42,
    28. address: 'London No. 1 Lake Park',
    29. },
    30. {
    31. key: '3',
    32. name: 'Joe Black',
    33. age: 32,
    34. address: 'Sidney No. 1 Lake Park',
    35. },
    36. {
    37. key: '4',
    38. name: 'Disabled User',
    39. age: 99,
    40. address: 'Sidney No. 1 Lake Park',
    41. },
    42. ];
    43. // rowSelection object indicates the need for row selection
    44. const rowSelection = {
    45. onChange: (selectedRowKeys, selectedRows) => {
    46. console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
    47. },
    48. getCheckboxProps: record => ({
    49. disabled: record.name === 'Disabled User', // Column configuration not to be checked
    50. name: record.name,
    51. }),
    52. };
    53. ReactDOM.render(
    54. <Table rowSelection={rowSelection} columns={columns} dataSource={data} />,
    55. mountNode,
    56. );

    Table 表格 - 图4

    选择和操作

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

    1. import { Table, Button } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. },
    7. {
    8. title: 'Age',
    9. dataIndex: 'age',
    10. },
    11. {
    12. title: 'Address',
    13. dataIndex: 'address',
    14. },
    15. ];
    16. const data = [];
    17. for (let i = 0; i < 46; i++) {
    18. data.push({
    19. key: i,
    20. name: `Edward King ${i}`,
    21. age: 32,
    22. address: `London, Park Lane no. ${i}`,
    23. });
    24. }
    25. class App extends React.Component {
    26. state = {
    27. selectedRowKeys: [], // Check here to configure the default column
    28. loading: false,
    29. };
    30. start = () => {
    31. this.setState({ loading: true });
    32. // ajax request after empty completing
    33. setTimeout(() => {
    34. this.setState({
    35. selectedRowKeys: [],
    36. loading: false,
    37. });
    38. }, 1000);
    39. };
    40. onSelectChange = selectedRowKeys => {
    41. console.log('selectedRowKeys changed: ', selectedRowKeys);
    42. this.setState({ selectedRowKeys });
    43. };
    44. render() {
    45. const { loading, selectedRowKeys } = this.state;
    46. const rowSelection = {
    47. selectedRowKeys,
    48. onChange: this.onSelectChange,
    49. };
    50. const hasSelected = selectedRowKeys.length > 0;
    51. return (
    52. <div>
    53. <div style={{ marginBottom: 16 }}>
    54. <Button type="primary" onClick={this.start} disabled={!hasSelected} loading={loading}>
    55. Reload
    56. </Button>
    57. <span style={{ marginLeft: 8 }}>
    58. {hasSelected ? `Selected ${selectedRowKeys.length} items` : ''}
    59. </span>
    60. </div>
    61. <Table rowSelection={rowSelection} columns={columns} dataSource={data} />
    62. </div>
    63. );
    64. }
    65. }
    66. ReactDOM.render(<App />, mountNode);

    Table 表格 - 图5

    自定义选择项

    通过 rowSelection.selections 自定义选择项,默认不显示下拉选项,设为 true 时显示默认选择项。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. },
    7. {
    8. title: 'Age',
    9. dataIndex: 'age',
    10. },
    11. {
    12. title: 'Address',
    13. dataIndex: 'address',
    14. },
    15. ];
    16. const data = [];
    17. for (let i = 0; i < 46; i++) {
    18. data.push({
    19. key: i,
    20. name: `Edward King ${i}`,
    21. age: 32,
    22. address: `London, Park Lane no. ${i}`,
    23. });
    24. }
    25. class App extends React.Component {
    26. state = {
    27. selectedRowKeys: [], // Check here to configure the default column
    28. };
    29. onSelectChange = selectedRowKeys => {
    30. console.log('selectedRowKeys changed: ', selectedRowKeys);
    31. this.setState({ selectedRowKeys });
    32. };
    33. render() {
    34. const { selectedRowKeys } = this.state;
    35. const rowSelection = {
    36. selectedRowKeys,
    37. onChange: this.onSelectChange,
    38. hideDefaultSelections: true,
    39. selections: [
    40. {
    41. key: 'all-data',
    42. text: 'Select All Data',
    43. onSelect: () => {
    44. this.setState({
    45. selectedRowKeys: [...Array(46).keys()], // 0...45
    46. });
    47. },
    48. },
    49. {
    50. key: 'odd',
    51. text: 'Select Odd Row',
    52. onSelect: changableRowKeys => {
    53. let newSelectedRowKeys = [];
    54. newSelectedRowKeys = changableRowKeys.filter((key, index) => {
    55. if (index % 2 !== 0) {
    56. return false;
    57. }
    58. return true;
    59. });
    60. this.setState({ selectedRowKeys: newSelectedRowKeys });
    61. },
    62. },
    63. {
    64. key: 'even',
    65. text: 'Select Even Row',
    66. onSelect: changableRowKeys => {
    67. let newSelectedRowKeys = [];
    68. newSelectedRowKeys = changableRowKeys.filter((key, index) => {
    69. if (index % 2 !== 0) {
    70. return true;
    71. }
    72. return false;
    73. });
    74. this.setState({ selectedRowKeys: newSelectedRowKeys });
    75. },
    76. },
    77. ],
    78. onSelection: this.onSelection,
    79. };
    80. return <Table rowSelection={rowSelection} columns={columns} dataSource={data} />;
    81. }
    82. }
    83. ReactDOM.render(<App />, mountNode);

    Table 表格 - 图6

    筛选和排序

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

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

    sortDirections: ['ascend' | 'descend']改变每列可用的排序方式,切换排序时按数组内容依次切换,设置在 table props 上时对所有列生效。

    使用 defaultSortOrder 属性,设置列的默认排序顺序。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. filters: [
    7. {
    8. text: 'Joe',
    9. value: 'Joe',
    10. },
    11. {
    12. text: 'Jim',
    13. value: 'Jim',
    14. },
    15. {
    16. text: 'Submenu',
    17. value: 'Submenu',
    18. children: [
    19. {
    20. text: 'Green',
    21. value: 'Green',
    22. },
    23. {
    24. text: 'Black',
    25. value: 'Black',
    26. },
    27. ],
    28. },
    29. ],
    30. // specify the condition of filtering result
    31. // here is that finding the name started with `value`
    32. onFilter: (value, record) => record.name.indexOf(value) === 0,
    33. sorter: (a, b) => a.name.length - b.name.length,
    34. sortDirections: ['descend'],
    35. },
    36. {
    37. title: 'Age',
    38. dataIndex: 'age',
    39. defaultSortOrder: 'descend',
    40. sorter: (a, b) => a.age - b.age,
    41. },
    42. {
    43. title: 'Address',
    44. dataIndex: 'address',
    45. filters: [
    46. {
    47. text: 'London',
    48. value: 'London',
    49. },
    50. {
    51. text: 'New York',
    52. value: 'New York',
    53. },
    54. ],
    55. filterMultiple: false,
    56. onFilter: (value, record) => record.address.indexOf(value) === 0,
    57. sorter: (a, b) => a.address.length - b.address.length,
    58. sortDirections: ['descend', 'ascend'],
    59. },
    60. ];
    61. const data = [
    62. {
    63. key: '1',
    64. name: 'John Brown',
    65. age: 32,
    66. address: 'New York No. 1 Lake Park',
    67. },
    68. {
    69. key: '2',
    70. name: 'Jim Green',
    71. age: 42,
    72. address: 'London No. 1 Lake Park',
    73. },
    74. {
    75. key: '3',
    76. name: 'Joe Black',
    77. age: 32,
    78. address: 'Sidney No. 1 Lake Park',
    79. },
    80. {
    81. key: '4',
    82. name: 'Jim Red',
    83. age: 32,
    84. address: 'London No. 2 Lake Park',
    85. },
    86. ];
    87. function onChange(pagination, filters, sorter) {
    88. console.log('params', pagination, filters, sorter);
    89. }
    90. ReactDOM.render(<Table columns={columns} dataSource={data} onChange={onChange} />, mountNode);

    Table 表格 - 图7

    可控的筛选和排序

    使用受控属性对筛选和排序状态进行控制。

    1. columns 中定义了 filteredValue 和 sortOrder 属性即视为受控模式。

    2. 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。

    3. 务必指定 column.key

    1. import { Table, Button } from 'antd';
    2. const data = [
    3. {
    4. key: '1',
    5. name: 'John Brown',
    6. age: 32,
    7. address: 'New York No. 1 Lake Park',
    8. },
    9. {
    10. key: '2',
    11. name: 'Jim Green',
    12. age: 42,
    13. address: 'London No. 1 Lake Park',
    14. },
    15. {
    16. key: '3',
    17. name: 'Joe Black',
    18. age: 32,
    19. address: 'Sidney No. 1 Lake Park',
    20. },
    21. {
    22. key: '4',
    23. name: 'Jim Red',
    24. age: 32,
    25. address: 'London No. 2 Lake Park',
    26. },
    27. ];
    28. class App extends React.Component {
    29. state = {
    30. filteredInfo: null,
    31. sortedInfo: null,
    32. };
    33. handleChange = (pagination, filters, sorter) => {
    34. console.log('Various parameters', pagination, filters, sorter);
    35. this.setState({
    36. filteredInfo: filters,
    37. sortedInfo: sorter,
    38. });
    39. };
    40. clearFilters = () => {
    41. this.setState({ filteredInfo: null });
    42. };
    43. clearAll = () => {
    44. this.setState({
    45. filteredInfo: null,
    46. sortedInfo: null,
    47. });
    48. };
    49. setAgeSort = () => {
    50. this.setState({
    51. sortedInfo: {
    52. order: 'descend',
    53. columnKey: 'age',
    54. },
    55. });
    56. };
    57. render() {
    58. let { sortedInfo, filteredInfo } = this.state;
    59. sortedInfo = sortedInfo || {};
    60. filteredInfo = filteredInfo || {};
    61. const columns = [
    62. {
    63. title: 'Name',
    64. dataIndex: 'name',
    65. key: 'name',
    66. filters: [{ text: 'Joe', value: 'Joe' }, { text: 'Jim', value: 'Jim' }],
    67. filteredValue: filteredInfo.name || null,
    68. onFilter: (value, record) => record.name.includes(value),
    69. sorter: (a, b) => a.name.length - b.name.length,
    70. sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
    71. },
    72. {
    73. title: 'Age',
    74. dataIndex: 'age',
    75. key: 'age',
    76. sorter: (a, b) => a.age - b.age,
    77. sortOrder: sortedInfo.columnKey === 'age' && sortedInfo.order,
    78. },
    79. {
    80. title: 'Address',
    81. dataIndex: 'address',
    82. key: 'address',
    83. filters: [{ text: 'London', value: 'London' }, { text: 'New York', value: 'New York' }],
    84. filteredValue: filteredInfo.address || null,
    85. onFilter: (value, record) => record.address.includes(value),
    86. sorter: (a, b) => a.address.length - b.address.length,
    87. sortOrder: sortedInfo.columnKey === 'address' && sortedInfo.order,
    88. },
    89. ];
    90. return (
    91. <div>
    92. <div className="table-operations">
    93. <Button onClick={this.setAgeSort}>Sort age</Button>
    94. <Button onClick={this.clearFilters}>Clear filters</Button>
    95. <Button onClick={this.clearAll}>Clear filters and sorters</Button>
    96. </div>
    97. <Table columns={columns} dataSource={data} onChange={this.handleChange} />
    98. </div>
    99. );
    100. }
    101. }
    102. ReactDOM.render(<App />, mountNode);
    1. .table-operations {
    2. margin-bottom: 16px;
    3. }
    4. .table-operations > button {
    5. margin-right: 8px;
    6. }

    Table 表格 - 图8

    自定义筛选菜单

    通过 filterDropdown 自定义的列筛选功能,并实现一个搜索列的示例。

    1. import { Table, Input, Button, Icon } from 'antd';
    2. import Highlighter from 'react-highlight-words';
    3. const data = [
    4. {
    5. key: '1',
    6. name: 'John Brown',
    7. age: 32,
    8. address: 'New York No. 1 Lake Park',
    9. },
    10. {
    11. key: '2',
    12. name: 'Joe Black',
    13. age: 42,
    14. address: 'London No. 1 Lake Park',
    15. },
    16. {
    17. key: '3',
    18. name: 'Jim Green',
    19. age: 32,
    20. address: 'Sidney No. 1 Lake Park',
    21. },
    22. {
    23. key: '4',
    24. name: 'Jim Red',
    25. age: 32,
    26. address: 'London No. 2 Lake Park',
    27. },
    28. ];
    29. class App extends React.Component {
    30. state = {
    31. searchText: '',
    32. };
    33. getColumnSearchProps = dataIndex => ({
    34. filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
    35. <div style={{ padding: 8 }}>
    36. <Input
    37. ref={node => {
    38. this.searchInput = node;
    39. }}
    40. placeholder={`Search ${dataIndex}`}
    41. value={selectedKeys[0]}
    42. onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
    43. onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
    44. style={{ width: 188, marginBottom: 8, display: 'block' }}
    45. />
    46. <Button
    47. type="primary"
    48. onClick={() => this.handleSearch(selectedKeys, confirm)}
    49. icon="search"
    50. size="small"
    51. style={{ width: 90, marginRight: 8 }}
    52. >
    53. Search
    54. </Button>
    55. <Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
    56. Reset
    57. </Button>
    58. </div>
    59. ),
    60. filterIcon: filtered => (
    61. <Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} />
    62. ),
    63. onFilter: (value, record) =>
    64. record[dataIndex]
    65. .toString()
    66. .toLowerCase()
    67. .includes(value.toLowerCase()),
    68. onFilterDropdownVisibleChange: visible => {
    69. if (visible) {
    70. setTimeout(() => this.searchInput.select());
    71. }
    72. },
    73. render: text => (
    74. <Highlighter
    75. highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
    76. searchWords={[this.state.searchText]}
    77. autoEscape
    78. textToHighlight={text.toString()}
    79. />
    80. ),
    81. });
    82. handleSearch = (selectedKeys, confirm) => {
    83. confirm();
    84. this.setState({ searchText: selectedKeys[0] });
    85. };
    86. handleReset = clearFilters => {
    87. clearFilters();
    88. this.setState({ searchText: '' });
    89. };
    90. render() {
    91. const columns = [
    92. {
    93. title: 'Name',
    94. dataIndex: 'name',
    95. key: 'name',
    96. width: '30%',
    97. ...this.getColumnSearchProps('name'),
    98. },
    99. {
    100. title: 'Age',
    101. dataIndex: 'age',
    102. key: 'age',
    103. width: '20%',
    104. ...this.getColumnSearchProps('age'),
    105. },
    106. {
    107. title: 'Address',
    108. dataIndex: 'address',
    109. key: 'address',
    110. ...this.getColumnSearchProps('address'),
    111. },
    112. ];
    113. return <Table columns={columns} dataSource={data} />;
    114. }
    115. }
    116. ReactDOM.render(<App />, mountNode);

    Table 表格 - 图9

    远程加载数据

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

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

    注意,此示例使用 模拟接口,展示数据可能不准确,请打开网络面板查看请求。

    1. import { Table } from 'antd';
    2. import reqwest from 'reqwest';
    3. const columns = [
    4. {
    5. title: 'Name',
    6. dataIndex: 'name',
    7. sorter: true,
    8. render: name => `${name.first} ${name.last}`,
    9. width: '20%',
    10. },
    11. {
    12. title: 'Gender',
    13. dataIndex: 'gender',
    14. filters: [{ text: 'Male', value: 'male' }, { text: 'Female', value: 'female' }],
    15. width: '20%',
    16. },
    17. {
    18. title: 'Email',
    19. dataIndex: 'email',
    20. },
    21. ];
    22. class App extends React.Component {
    23. state = {
    24. data: [],
    25. pagination: {},
    26. loading: false,
    27. };
    28. componentDidMount() {
    29. this.fetch();
    30. }
    31. handleTableChange = (pagination, filters, sorter) => {
    32. const pager = { ...this.state.pagination };
    33. pager.current = pagination.current;
    34. this.setState({
    35. pagination: pager,
    36. });
    37. this.fetch({
    38. results: pagination.pageSize,
    39. page: pagination.current,
    40. sortField: sorter.field,
    41. sortOrder: sorter.order,
    42. ...filters,
    43. });
    44. };
    45. fetch = (params = {}) => {
    46. console.log('params:', params);
    47. this.setState({ loading: true });
    48. reqwest({
    49. url: 'https://randomuser.me/api',
    50. method: 'get',
    51. data: {
    52. results: 10,
    53. ...params,
    54. },
    55. type: 'json',
    56. }).then(data => {
    57. const pagination = { ...this.state.pagination };
    58. // Read total count from server
    59. // pagination.total = data.totalCount;
    60. pagination.total = 200;
    61. this.setState({
    62. loading: false,
    63. data: data.results,
    64. pagination,
    65. });
    66. });
    67. };
    68. render() {
    69. return (
    70. <Table
    71. columns={columns}
    72. rowKey={record => record.login.uuid}
    73. dataSource={this.state.data}
    74. pagination={this.state.pagination}
    75. loading={this.state.loading}
    76. onChange={this.handleTableChange}
    77. />
    78. );
    79. }
    80. }
    81. ReactDOM.render(<App />, mountNode);

    Table 表格 - 图10

    紧凑型

    两种紧凑型的列表,小型列表只用于对话框内。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. },
    7. {
    8. title: 'Age',
    9. dataIndex: 'age',
    10. },
    11. {
    12. title: 'Address',
    13. dataIndex: 'address',
    14. },
    15. ];
    16. const data = [
    17. {
    18. key: '1',
    19. name: 'John Brown',
    20. age: 32,
    21. address: 'New York No. 1 Lake Park',
    22. },
    23. {
    24. key: '2',
    25. name: 'Jim Green',
    26. age: 42,
    27. address: 'London No. 1 Lake Park',
    28. },
    29. {
    30. key: '3',
    31. name: 'Joe Black',
    32. age: 32,
    33. address: 'Sidney No. 1 Lake Park',
    34. },
    35. ];
    36. ReactDOM.render(
    37. <div>
    38. <h4>Middle size table</h4>
    39. <Table columns={columns} dataSource={data} size="middle" />
    40. <h4>Small size table</h4>
    41. <Table columns={columns} dataSource={data} size="small" />
    42. </div>,
    43. mountNode,
    44. );

    Table 表格 - 图11

    带边框

    添加表格边框线,页头和页脚。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. render: text => <a href="javascript:;">{text}</a>,
    7. },
    8. {
    9. title: 'Cash Assets',
    10. className: 'column-money',
    11. dataIndex: 'money',
    12. },
    13. {
    14. title: 'Address',
    15. dataIndex: 'address',
    16. },
    17. ];
    18. const data = [
    19. {
    20. key: '1',
    21. name: 'John Brown',
    22. money: '¥300,000.00',
    23. address: 'New York No. 1 Lake Park',
    24. },
    25. {
    26. key: '2',
    27. name: 'Jim Green',
    28. money: '¥1,256,000.00',
    29. address: 'London No. 1 Lake Park',
    30. },
    31. {
    32. key: '3',
    33. name: 'Joe Black',
    34. money: '¥120,000.00',
    35. address: 'Sidney No. 1 Lake Park',
    36. },
    37. ];
    38. ReactDOM.render(
    39. <Table
    40. columns={columns}
    41. dataSource={data}
    42. bordered
    43. title={() => 'Header'}
    44. footer={() => 'Footer'}
    45. />,
    46. mountNode,
    47. );
    1. th.column-money,
    2. td.column-money {
    3. text-align: right !important;
    4. }

    Table 表格 - 图12

    可展开

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

    1. import { Table } from 'antd';
    2. const columns = [
    3. { title: 'Name', dataIndex: 'name', key: 'name' },
    4. { title: 'Age', dataIndex: 'age', key: 'age' },
    5. { title: 'Address', dataIndex: 'address', key: 'address' },
    6. {
    7. title: 'Action',
    8. dataIndex: '',
    9. key: 'x',
    10. render: () => <a href="javascript:;">Delete</a>,
    11. },
    12. ];
    13. const data = [
    14. {
    15. key: 1,
    16. name: 'John Brown',
    17. age: 32,
    18. address: 'New York No. 1 Lake Park',
    19. description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
    20. },
    21. {
    22. key: 2,
    23. name: 'Jim Green',
    24. age: 42,
    25. address: 'London No. 1 Lake Park',
    26. description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
    27. },
    28. {
    29. key: 3,
    30. name: 'Joe Black',
    31. age: 32,
    32. address: 'Sidney No. 1 Lake Park',
    33. description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
    34. },
    35. ];
    36. ReactDOM.render(
    37. <Table
    38. columns={columns}
    39. expandedRowRender={record => <p style={{ margin: 0 }}>{record.description}</p>}
    40. dataSource={data}
    41. />,
    42. mountNode,
    43. );

    Table 表格 - 图13

    表格行/列合并

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

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

    1. import { Table } from 'antd';
    2. // In the fifth row, other columns are merged into first column
    3. // by setting it's colSpan to be 0
    4. const renderContent = (value, row, index) => {
    5. const obj = {
    6. children: value,
    7. props: {},
    8. };
    9. if (index === 4) {
    10. obj.props.colSpan = 0;
    11. }
    12. return obj;
    13. };
    14. const columns = [
    15. {
    16. title: 'Name',
    17. dataIndex: 'name',
    18. render: (text, row, index) => {
    19. if (index < 4) {
    20. return <a href="javascript:;">{text}</a>;
    21. }
    22. return {
    23. children: <a href="javascript:;">{text}</a>,
    24. props: {
    25. colSpan: 5,
    26. },
    27. };
    28. },
    29. },
    30. {
    31. title: 'Age',
    32. dataIndex: 'age',
    33. render: renderContent,
    34. },
    35. {
    36. title: 'Home phone',
    37. colSpan: 2,
    38. dataIndex: 'tel',
    39. render: (value, row, index) => {
    40. const obj = {
    41. children: value,
    42. props: {},
    43. };
    44. if (index === 2) {
    45. obj.props.rowSpan = 2;
    46. }
    47. // These two are merged into above cell
    48. if (index === 3) {
    49. obj.props.rowSpan = 0;
    50. }
    51. if (index === 4) {
    52. obj.props.colSpan = 0;
    53. }
    54. return obj;
    55. },
    56. },
    57. {
    58. title: 'Phone',
    59. colSpan: 0,
    60. dataIndex: 'phone',
    61. render: renderContent,
    62. },
    63. {
    64. title: 'Address',
    65. dataIndex: 'address',
    66. render: renderContent,
    67. },
    68. ];
    69. const data = [
    70. {
    71. key: '1',
    72. name: 'John Brown',
    73. age: 32,
    74. tel: '0571-22098909',
    75. phone: 18889898989,
    76. address: 'New York No. 1 Lake Park',
    77. },
    78. {
    79. key: '2',
    80. name: 'Jim Green',
    81. tel: '0571-22098333',
    82. phone: 18889898888,
    83. age: 42,
    84. address: 'London No. 1 Lake Park',
    85. },
    86. {
    87. key: '3',
    88. name: 'Joe Black',
    89. age: 32,
    90. tel: '0575-22098909',
    91. phone: 18900010002,
    92. address: 'Sidney No. 1 Lake Park',
    93. },
    94. {
    95. key: '4',
    96. name: 'Jim Red',
    97. age: 18,
    98. tel: '0575-22098909',
    99. phone: 18900010002,
    100. address: 'London No. 2 Lake Park',
    101. },
    102. {
    103. key: '5',
    104. name: 'Jake White',
    105. age: 18,
    106. tel: '0575-22098909',
    107. phone: 18900010002,
    108. address: 'Dublin No. 2 Lake Park',
    109. },
    110. ];
    111. ReactDOM.render(<Table columns={columns} dataSource={data} bordered />, mountNode);

    Table 表格 - 图14

    树形数据展示

    表格支持树形数据的展示,当数据中有 children 字段时会自动展示为树形表格,如果不需要或配置为其他字段可以用 childrenColumnName 进行配置。

    可以通过设置 indentSize 以控制每一层的缩进宽度。

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

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. key: 'name',
    7. },
    8. {
    9. title: 'Age',
    10. dataIndex: 'age',
    11. key: 'age',
    12. width: '12%',
    13. },
    14. {
    15. title: 'Address',
    16. dataIndex: 'address',
    17. width: '30%',
    18. key: 'address',
    19. },
    20. ];
    21. const data = [
    22. {
    23. key: 1,
    24. name: 'John Brown sr.',
    25. age: 60,
    26. address: 'New York No. 1 Lake Park',
    27. children: [
    28. {
    29. key: 11,
    30. name: 'John Brown',
    31. age: 42,
    32. address: 'New York No. 2 Lake Park',
    33. },
    34. {
    35. key: 12,
    36. name: 'John Brown jr.',
    37. age: 30,
    38. address: 'New York No. 3 Lake Park',
    39. children: [
    40. {
    41. key: 121,
    42. name: 'Jimmy Brown',
    43. age: 16,
    44. address: 'New York No. 3 Lake Park',
    45. },
    46. ],
    47. },
    48. {
    49. key: 13,
    50. name: 'Jim Green sr.',
    51. age: 72,
    52. address: 'London No. 1 Lake Park',
    53. children: [
    54. {
    55. key: 131,
    56. name: 'Jim Green',
    57. age: 42,
    58. address: 'London No. 2 Lake Park',
    59. children: [
    60. {
    61. key: 1311,
    62. name: 'Jim Green jr.',
    63. age: 25,
    64. address: 'London No. 3 Lake Park',
    65. },
    66. {
    67. key: 1312,
    68. name: 'Jimmy Green sr.',
    69. age: 18,
    70. address: 'London No. 4 Lake Park',
    71. },
    72. ],
    73. },
    74. ],
    75. },
    76. ],
    77. },
    78. {
    79. key: 2,
    80. name: 'Joe Black',
    81. age: 32,
    82. address: 'Sidney No. 1 Lake Park',
    83. },
    84. ];
    85. // rowSelection objects indicates the need for row selection
    86. const rowSelection = {
    87. onChange: (selectedRowKeys, selectedRows) => {
    88. console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
    89. },
    90. onSelect: (record, selected, selectedRows) => {
    91. console.log(record, selected, selectedRows);
    92. },
    93. onSelectAll: (selected, selectedRows, changeRows) => {
    94. console.log(selected, selectedRows, changeRows);
    95. },
    96. };
    97. ReactDOM.render(
    98. <Table columns={columns} rowSelection={rowSelection} dataSource={data} />,
    99. mountNode,
    100. );

    Table 表格 - 图15

    固定表头

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

    需要指定 column 的 width 属性,否则列头和内容可能不对齐。如果指定 width 不生效,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. width: 150,
    7. },
    8. {
    9. title: 'Age',
    10. dataIndex: 'age',
    11. width: 150,
    12. },
    13. {
    14. title: 'Address',
    15. dataIndex: 'address',
    16. },
    17. ];
    18. const data = [];
    19. for (let i = 0; i < 100; i++) {
    20. data.push({
    21. key: i,
    22. name: `Edward King ${i}`,
    23. age: 32,
    24. address: `London, Park Lane no. ${i}`,
    25. });
    26. }
    27. ReactDOM.render(
    28. <Table columns={columns} dataSource={data} pagination={{ pageSize: 50 }} scroll={{ y: 240 }} />,
    29. mountNode,
    30. );

    Table 表格 - 图16

    固定列

    对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,需要和 scroll.x 配合使用。

    若列头与内容不对齐或出现列重复,请指定固定列的宽度 width。如果指定 width 不生效,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。

    建议指定 scroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 scroll.x

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Full Name',
    5. width: 100,
    6. dataIndex: 'name',
    7. key: 'name',
    8. fixed: 'left',
    9. },
    10. {
    11. title: 'Age',
    12. width: 100,
    13. dataIndex: 'age',
    14. key: 'age',
    15. fixed: 'left',
    16. },
    17. { title: 'Column 1', dataIndex: 'address', key: '1' },
    18. { title: 'Column 2', dataIndex: 'address', key: '2' },
    19. { title: 'Column 3', dataIndex: 'address', key: '3' },
    20. { title: 'Column 4', dataIndex: 'address', key: '4' },
    21. { title: 'Column 5', dataIndex: 'address', key: '5' },
    22. { title: 'Column 6', dataIndex: 'address', key: '6' },
    23. { title: 'Column 7', dataIndex: 'address', key: '7' },
    24. { title: 'Column 8', dataIndex: 'address', key: '8' },
    25. {
    26. title: 'Action',
    27. key: 'operation',
    28. fixed: 'right',
    29. width: 100,
    30. render: () => <a href="javascript:;">action</a>,
    31. },
    32. ];
    33. const data = [
    34. {
    35. key: '1',
    36. name: 'John Brown',
    37. age: 32,
    38. address: 'New York Park',
    39. },
    40. {
    41. key: '2',
    42. name: 'Jim Green',
    43. age: 40,
    44. address: 'London Park',
    45. },
    46. ];
    47. ReactDOM.render(<Table columns={columns} dataSource={data} scroll={{ x: 1300 }} />, mountNode);

    Table 表格 - 图17

    固定头和列

    适合同时展示有大量数据和数据列。

    若列头与内容不对齐或出现列重复,请指定固定列的宽度 width。如果指定 width 不生效,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。

    建议指定 scroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 scroll.x

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Full Name',
    5. width: 100,
    6. dataIndex: 'name',
    7. key: 'name',
    8. fixed: 'left',
    9. },
    10. {
    11. title: 'Age',
    12. width: 100,
    13. dataIndex: 'age',
    14. key: 'age',
    15. fixed: 'left',
    16. },
    17. {
    18. title: 'Column 1',
    19. dataIndex: 'address',
    20. key: '1',
    21. width: 150,
    22. },
    23. {
    24. title: 'Column 2',
    25. dataIndex: 'address',
    26. key: '2',
    27. width: 150,
    28. },
    29. {
    30. title: 'Column 3',
    31. dataIndex: 'address',
    32. key: '3',
    33. width: 150,
    34. },
    35. {
    36. title: 'Column 4',
    37. dataIndex: 'address',
    38. key: '4',
    39. width: 150,
    40. },
    41. {
    42. title: 'Column 5',
    43. dataIndex: 'address',
    44. key: '5',
    45. width: 150,
    46. },
    47. {
    48. title: 'Column 6',
    49. dataIndex: 'address',
    50. key: '6',
    51. width: 150,
    52. },
    53. {
    54. title: 'Column 7',
    55. dataIndex: 'address',
    56. key: '7',
    57. width: 150,
    58. },
    59. { title: 'Column 8', dataIndex: 'address', key: '8' },
    60. {
    61. title: 'Action',
    62. key: 'operation',
    63. fixed: 'right',
    64. width: 100,
    65. render: () => <a href="javascript:;">action</a>,
    66. },
    67. ];
    68. const data = [];
    69. for (let i = 0; i < 100; i++) {
    70. data.push({
    71. key: i,
    72. name: `Edrward ${i}`,
    73. age: 32,
    74. address: `London Park no. ${i}`,
    75. });
    76. }
    77. ReactDOM.render(
    78. <Table columns={columns} dataSource={data} scroll={{ x: 1500, y: 300 }} />,
    79. mountNode,
    80. );

    Table 表格 - 图18

    表头分组

    columns[n] 可以内嵌 children,以渲染分组表头。

    1. import { Table } from 'antd';
    2. const columns = [
    3. {
    4. title: 'Name',
    5. dataIndex: 'name',
    6. key: 'name',
    7. width: 100,
    8. fixed: 'left',
    9. filters: [
    10. {
    11. text: 'Joe',
    12. value: 'Joe',
    13. },
    14. {
    15. text: 'John',
    16. value: 'John',
    17. },
    18. ],
    19. onFilter: (value, record) => record.name.indexOf(value) === 0,
    20. },
    21. {
    22. title: 'Other',
    23. children: [
    24. {
    25. title: 'Age',
    26. dataIndex: 'age',
    27. key: 'age',
    28. width: 200,
    29. sorter: (a, b) => a.age - b.age,
    30. },
    31. {
    32. title: 'Address',
    33. children: [
    34. {
    35. title: 'Street',
    36. dataIndex: 'street',
    37. key: 'street',
    38. width: 200,
    39. },
    40. {
    41. title: 'Block',
    42. children: [
    43. {
    44. title: 'Building',
    45. dataIndex: 'building',
    46. key: 'building',
    47. width: 100,
    48. },
    49. {
    50. title: 'Door No.',
    51. dataIndex: 'number',
    52. key: 'number',
    53. width: 100,
    54. },
    55. ],
    56. },
    57. ],
    58. },
    59. ],
    60. },
    61. {
    62. title: 'Company',
    63. children: [
    64. {
    65. title: 'Company Address',
    66. dataIndex: 'companyAddress',
    67. key: 'companyAddress',
    68. },
    69. {
    70. title: 'Company Name',
    71. dataIndex: 'companyName',
    72. key: 'companyName',
    73. },
    74. ],
    75. },
    76. {
    77. title: 'Gender',
    78. dataIndex: 'gender',
    79. key: 'gender',
    80. width: 80,
    81. fixed: 'right',
    82. },
    83. ];
    84. const data = [];
    85. for (let i = 0; i < 100; i++) {
    86. data.push({
    87. key: i,
    88. name: 'John Brown',
    89. age: i + 1,
    90. street: 'Lake Park',
    91. building: 'C',
    92. number: 2035,
    93. companyAddress: 'Lake Street 42',
    94. companyName: 'SoftLake Co',
    95. gender: 'M',
    96. });
    97. }
    98. ReactDOM.render(
    99. <Table
    100. columns={columns}
    101. dataSource={data}
    102. bordered
    103. size="middle"
    104. scroll={{ x: '130%', y: 240 }}
    105. />,
    106. mountNode,
    107. );

    Table 表格 - 图19

    可编辑单元格

    带单元格编辑功能的表格。

    1. import { Table, Input, Button, Popconfirm, Form } from 'antd';
    2. const EditableContext = React.createContext();
    3. const EditableRow = ({ form, index, ...props }) => (
    4. <EditableContext.Provider value={form}>
    5. <tr {...props} />
    6. </EditableContext.Provider>
    7. );
    8. const EditableFormRow = Form.create()(EditableRow);
    9. class EditableCell extends React.Component {
    10. state = {
    11. editing: false,
    12. };
    13. toggleEdit = () => {
    14. const editing = !this.state.editing;
    15. this.setState({ editing }, () => {
    16. if (editing) {
    17. this.input.focus();
    18. }
    19. });
    20. };
    21. save = e => {
    22. const { record, handleSave } = this.props;
    23. this.form.validateFields((error, values) => {
    24. if (error && error[e.currentTarget.id]) {
    25. return;
    26. }
    27. this.toggleEdit();
    28. handleSave({ ...record, ...values });
    29. });
    30. };
    31. renderCell = form => {
    32. this.form = form;
    33. const { children, dataIndex, record, title } = this.props;
    34. const { editing } = this.state;
    35. return editing ? (
    36. <Form.Item style={{ margin: 0 }}>
    37. {form.getFieldDecorator(dataIndex, {
    38. rules: [
    39. {
    40. required: true,
    41. message: `${title} is required.`,
    42. },
    43. ],
    44. initialValue: record[dataIndex],
    45. })(<Input ref={node => (this.input = node)} onPressEnter={this.save} onBlur={this.save} />)}
    46. </Form.Item>
    47. ) : (
    48. <div
    49. className="editable-cell-value-wrap"
    50. style={{ paddingRight: 24 }}
    51. onClick={this.toggleEdit}
    52. >
    53. {children}
    54. </div>
    55. );
    56. };
    57. render() {
    58. const {
    59. editable,
    60. dataIndex,
    61. title,
    62. record,
    63. index,
    64. handleSave,
    65. children,
    66. ...restProps
    67. } = this.props;
    68. return (
    69. <td {...restProps}>
    70. {editable ? (
    71. <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
    72. ) : (
    73. children
    74. )}
    75. </td>
    76. );
    77. }
    78. }
    79. class EditableTable extends React.Component {
    80. constructor(props) {
    81. super(props);
    82. this.columns = [
    83. {
    84. title: 'name',
    85. dataIndex: 'name',
    86. width: '30%',
    87. editable: true,
    88. },
    89. {
    90. title: 'age',
    91. dataIndex: 'age',
    92. },
    93. {
    94. title: 'address',
    95. dataIndex: 'address',
    96. },
    97. {
    98. title: 'operation',
    99. dataIndex: 'operation',
    100. render: (text, record) =>
    101. this.state.dataSource.length >= 1 ? (
    102. <Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
    103. <a href="javascript:;">Delete</a>
    104. </Popconfirm>
    105. ) : null,
    106. },
    107. ];
    108. this.state = {
    109. dataSource: [
    110. {
    111. key: '0',
    112. name: 'Edward King 0',
    113. age: '32',
    114. address: 'London, Park Lane no. 0',
    115. },
    116. {
    117. key: '1',
    118. name: 'Edward King 1',
    119. age: '32',
    120. address: 'London, Park Lane no. 1',
    121. },
    122. ],
    123. count: 2,
    124. };
    125. }
    126. handleDelete = key => {
    127. const dataSource = [...this.state.dataSource];
    128. this.setState({ dataSource: dataSource.filter(item => item.key !== key) });
    129. };
    130. handleAdd = () => {
    131. const { count, dataSource } = this.state;
    132. const newData = {
    133. key: count,
    134. name: `Edward King ${count}`,
    135. age: 32,
    136. address: `London, Park Lane no. ${count}`,
    137. };
    138. this.setState({
    139. dataSource: [...dataSource, newData],
    140. count: count + 1,
    141. });
    142. };
    143. handleSave = row => {
    144. const newData = [...this.state.dataSource];
    145. const index = newData.findIndex(item => row.key === item.key);
    146. const item = newData[index];
    147. newData.splice(index, 1, {
    148. ...item,
    149. ...row,
    150. });
    151. this.setState({ dataSource: newData });
    152. };
    153. render() {
    154. const { dataSource } = this.state;
    155. const components = {
    156. body: {
    157. row: EditableFormRow,
    158. cell: EditableCell,
    159. },
    160. };
    161. const columns = this.columns.map(col => {
    162. if (!col.editable) {
    163. return col;
    164. }
    165. return {
    166. ...col,
    167. onCell: record => ({
    168. record,
    169. editable: col.editable,
    170. dataIndex: col.dataIndex,
    171. title: col.title,
    172. handleSave: this.handleSave,
    173. }),
    174. };
    175. });
    176. return (
    177. <div>
    178. <Button onClick={this.handleAdd} type="primary" style={{ marginBottom: 16 }}>
    179. Add a row
    180. </Button>
    181. <Table
    182. components={components}
    183. rowClassName={() => 'editable-row'}
    184. bordered
    185. dataSource={dataSource}
    186. columns={columns}
    187. />
    188. </div>
    189. );
    190. }
    191. }
    192. ReactDOM.render(<EditableTable />, mountNode);
    1. .editable-cell {
    2. position: relative;
    3. }
    4. .editable-cell-value-wrap {
    5. padding: 5px 12px;
    6. cursor: pointer;
    7. }
    8. .editable-row:hover .editable-cell-value-wrap {
    9. border: 1px solid #d9d9d9;
    10. border-radius: 4px;
    11. padding: 4px 11px;
    12. }

    Table 表格 - 图20

    可编辑行

    带行编辑功能的表格。

    1. import { Table, Input, InputNumber, Popconfirm, Form } from 'antd';
    2. const data = [];
    3. for (let i = 0; i < 100; i++) {
    4. data.push({
    5. key: i.toString(),
    6. name: `Edrward ${i}`,
    7. age: 32,
    8. address: `London Park no. ${i}`,
    9. });
    10. }
    11. const EditableContext = React.createContext();
    12. class EditableCell extends React.Component {
    13. getInput = () => {
    14. if (this.props.inputType === 'number') {
    15. return <InputNumber />;
    16. }
    17. return <Input />;
    18. };
    19. renderCell = ({ getFieldDecorator }) => {
    20. const {
    21. editing,
    22. dataIndex,
    23. title,
    24. inputType,
    25. record,
    26. index,
    27. children,
    28. ...restProps
    29. } = this.props;
    30. return (
    31. <td {...restProps}>
    32. {editing ? (
    33. <Form.Item style={{ margin: 0 }}>
    34. {getFieldDecorator(dataIndex, {
    35. rules: [
    36. {
    37. required: true,
    38. message: `Please Input ${title}!`,
    39. },
    40. ],
    41. initialValue: record[dataIndex],
    42. })(this.getInput())}
    43. </Form.Item>
    44. ) : (
    45. children
    46. )}
    47. </td>
    48. );
    49. };
    50. render() {
    51. return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>;
    52. }
    53. }
    54. class EditableTable extends React.Component {
    55. constructor(props) {
    56. super(props);
    57. this.state = { data, editingKey: '' };
    58. this.columns = [
    59. {
    60. title: 'name',
    61. dataIndex: 'name',
    62. width: '25%',
    63. editable: true,
    64. },
    65. {
    66. title: 'age',
    67. dataIndex: 'age',
    68. width: '15%',
    69. editable: true,
    70. },
    71. {
    72. title: 'address',
    73. dataIndex: 'address',
    74. width: '40%',
    75. editable: true,
    76. },
    77. {
    78. title: 'operation',
    79. dataIndex: 'operation',
    80. render: (text, record) => {
    81. const { editingKey } = this.state;
    82. const editable = this.isEditing(record);
    83. return editable ? (
    84. <span>
    85. <EditableContext.Consumer>
    86. {form => (
    87. <a
    88. href="javascript:;"
    89. onClick={() => this.save(form, record.key)}
    90. style={{ marginRight: 8 }}
    91. >
    92. Save
    93. </a>
    94. )}
    95. </EditableContext.Consumer>
    96. <Popconfirm title="Sure to cancel?" onConfirm={() => this.cancel(record.key)}>
    97. <a>Cancel</a>
    98. </Popconfirm>
    99. </span>
    100. ) : (
    101. <a disabled={editingKey !== ''} onClick={() => this.edit(record.key)}>
    102. Edit
    103. </a>
    104. );
    105. },
    106. },
    107. ];
    108. }
    109. isEditing = record => record.key === this.state.editingKey;
    110. cancel = () => {
    111. this.setState({ editingKey: '' });
    112. };
    113. save(form, key) {
    114. form.validateFields((error, row) => {
    115. if (error) {
    116. return;
    117. }
    118. const newData = [...this.state.data];
    119. const index = newData.findIndex(item => key === item.key);
    120. if (index > -1) {
    121. const item = newData[index];
    122. newData.splice(index, 1, {
    123. ...item,
    124. ...row,
    125. });
    126. this.setState({ data: newData, editingKey: '' });
    127. } else {
    128. newData.push(row);
    129. this.setState({ data: newData, editingKey: '' });
    130. }
    131. });
    132. }
    133. edit(key) {
    134. this.setState({ editingKey: key });
    135. }
    136. render() {
    137. const components = {
    138. body: {
    139. cell: EditableCell,
    140. },
    141. };
    142. const columns = this.columns.map(col => {
    143. if (!col.editable) {
    144. return col;
    145. }
    146. return {
    147. ...col,
    148. onCell: record => ({
    149. record,
    150. inputType: col.dataIndex === 'age' ? 'number' : 'text',
    151. dataIndex: col.dataIndex,
    152. title: col.title,
    153. editing: this.isEditing(record),
    154. }),
    155. };
    156. });
    157. return (
    158. <EditableContext.Provider value={this.props.form}>
    159. <Table
    160. components={components}
    161. bordered
    162. dataSource={this.state.data}
    163. columns={columns}
    164. rowClassName="editable-row"
    165. pagination={{
    166. onChange: this.cancel,
    167. }}
    168. />
    169. </EditableContext.Provider>
    170. );
    171. }
    172. }
    173. const EditableFormTable = Form.create()(EditableTable);
    174. ReactDOM.render(<EditableFormTable />, mountNode);
    1. .editable-row .ant-form-explain {
    2. position: absolute;
    3. font-size: 12px;
    4. margin-top: -4px;
    5. }

    Table 表格 - 图21

    嵌套子表格

    展示每行数据更详细的信息。

    1. import { Table, Badge, Menu, Dropdown, Icon } from 'antd';
    2. const menu = (
    3. <Menu>
    4. <Menu.Item>Action 1</Menu.Item>
    5. <Menu.Item>Action 2</Menu.Item>
    6. </Menu>
    7. );
    8. function NestedTable() {
    9. const expandedRowRender = () => {
    10. const columns = [
    11. { title: 'Date', dataIndex: 'date', key: 'date' },
    12. { title: 'Name', dataIndex: 'name', key: 'name' },
    13. {
    14. title: 'Status',
    15. key: 'state',
    16. render: () => (
    17. <span>
    18. <Badge status="success" />
    19. Finished
    20. </span>
    21. ),
    22. },
    23. { title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
    24. {
    25. title: 'Action',
    26. dataIndex: 'operation',
    27. key: 'operation',
    28. render: () => (
    29. <span className="table-operation">
    30. <a href="javascript:;">Pause</a>
    31. <a href="javascript:;">Stop</a>
    32. <Dropdown overlay={menu}>
    33. <a href="javascript:;">
    34. More <Icon type="down" />
    35. </a>
    36. </Dropdown>
    37. </span>
    38. ),
    39. },
    40. ];
    41. const data = [];
    42. for (let i = 0; i < 3; ++i) {
    43. data.push({
    44. key: i,
    45. date: '2014-12-24 23:12:00',
    46. name: 'This is production name',
    47. upgradeNum: 'Upgraded: 56',
    48. });
    49. }
    50. return <Table columns={columns} dataSource={data} pagination={false} />;
    51. };
    52. const columns = [
    53. { title: 'Name', dataIndex: 'name', key: 'name' },
    54. { title: 'Platform', dataIndex: 'platform', key: 'platform' },
    55. { title: 'Version', dataIndex: 'version', key: 'version' },
    56. { title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
    57. { title: 'Creator', dataIndex: 'creator', key: 'creator' },
    58. { title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
    59. { title: 'Action', key: 'operation', render: () => <a href="javascript:;">Publish</a> },
    60. ];
    61. const data = [];
    62. for (let i = 0; i < 3; ++i) {
    63. data.push({
    64. key: i,
    65. name: 'Screem',
    66. platform: 'iOS',
    67. version: '10.3.4.5654',
    68. upgradeNum: 500,
    69. creator: 'Jack',
    70. createdAt: '2014-12-24 23:12:00',
    71. });
    72. }
    73. return (
    74. <Table
    75. className="components-table-demo-nested"
    76. columns={columns}
    77. expandedRowRender={expandedRowRender}
    78. dataSource={data}
    79. />
    80. );
    81. }
    82. ReactDOM.render(<NestedTable />, mountNode);

    Table 表格 - 图22

    拖拽排序

    使用自定义元素,我们可以集成 react-dnd 来实现拖拽排序。

    1. import { Table } from 'antd';
    2. import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
    3. import HTML5Backend from 'react-dnd-html5-backend';
    4. import update from 'immutability-helper';
    5. let dragingIndex = -1;
    6. class BodyRow extends React.Component {
    7. render() {
    8. const { isOver, connectDragSource, connectDropTarget, moveRow, ...restProps } = this.props;
    9. const style = { ...restProps.style, cursor: 'move' };
    10. let className = restProps.className;
    11. if (isOver) {
    12. if (restProps.index > dragingIndex) {
    13. className += ' drop-over-downward';
    14. }
    15. if (restProps.index < dragingIndex) {
    16. className += ' drop-over-upward';
    17. }
    18. }
    19. return connectDragSource(
    20. connectDropTarget(<tr {...restProps} className={className} style={style} />),
    21. );
    22. }
    23. }
    24. const rowSource = {
    25. beginDrag(props) {
    26. dragingIndex = props.index;
    27. return {
    28. index: props.index,
    29. };
    30. },
    31. };
    32. const rowTarget = {
    33. drop(props, monitor) {
    34. const dragIndex = monitor.getItem().index;
    35. const hoverIndex = props.index;
    36. // Don't replace items with themselves
    37. if (dragIndex === hoverIndex) {
    38. return;
    39. }
    40. // Time to actually perform the action
    41. props.moveRow(dragIndex, hoverIndex);
    42. // Note: we're mutating the monitor item here!
    43. // Generally it's better to avoid mutations,
    44. // but it's good here for the sake of performance
    45. // to avoid expensive index searches.
    46. monitor.getItem().index = hoverIndex;
    47. },
    48. };
    49. const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
    50. connectDropTarget: connect.dropTarget(),
    51. isOver: monitor.isOver(),
    52. }))(
    53. DragSource('row', rowSource, connect => ({
    54. connectDragSource: connect.dragSource(),
    55. }))(BodyRow),
    56. );
    57. const columns = [
    58. {
    59. title: 'Name',
    60. dataIndex: 'name',
    61. key: 'name',
    62. },
    63. {
    64. title: 'Age',
    65. dataIndex: 'age',
    66. key: 'age',
    67. },
    68. {
    69. title: 'Address',
    70. dataIndex: 'address',
    71. key: 'address',
    72. },
    73. ];
    74. class DragSortingTable extends React.Component {
    75. state = {
    76. data: [
    77. {
    78. key: '1',
    79. name: 'John Brown',
    80. age: 32,
    81. address: 'New York No. 1 Lake Park',
    82. },
    83. {
    84. key: '2',
    85. name: 'Jim Green',
    86. age: 42,
    87. address: 'London No. 1 Lake Park',
    88. },
    89. {
    90. key: '3',
    91. name: 'Joe Black',
    92. age: 32,
    93. address: 'Sidney No. 1 Lake Park',
    94. },
    95. ],
    96. };
    97. components = {
    98. body: {
    99. row: DragableBodyRow,
    100. },
    101. };
    102. moveRow = (dragIndex, hoverIndex) => {
    103. const { data } = this.state;
    104. const dragRow = data[dragIndex];
    105. this.setState(
    106. update(this.state, {
    107. data: {
    108. $splice: [[dragIndex, 1], [hoverIndex, 0, dragRow]],
    109. },
    110. }),
    111. );
    112. };
    113. render() {
    114. return (
    115. <Table
    116. columns={columns}
    117. dataSource={this.state.data}
    118. components={this.components}
    119. onRow={(record, index) => ({
    120. index,
    121. moveRow: this.moveRow,
    122. })}
    123. />
    124. );
    125. }
    126. }
    127. const Demo = DragDropContext(HTML5Backend)(DragSortingTable);
    128. ReactDOM.render(<Demo />, mountNode);
    1. #components-table-demo-drag-sorting tr.drop-over-downward td {
    2. border-bottom: 2px dashed #1890ff;
    3. }
    4. #components-table-demo-drag-sorting tr.drop-over-upward td {
    5. border-top: 2px dashed #1890ff;
    6. }

    Table 表格 - 图23

    可伸缩列

    集成 react-resizable 来实现可伸缩列。

    1. import { Table } from 'antd';
    2. import { Resizable } from 'react-resizable';
    3. const ResizeableTitle = props => {
    4. const { onResize, width, ...restProps } = props;
    5. if (!width) {
    6. return <th {...restProps} />;
    7. }
    8. return (
    9. <Resizable width={width} height={0} onResize={onResize}>
    10. <th {...restProps} />
    11. </Resizable>
    12. );
    13. };
    14. class Demo extends React.Component {
    15. state = {
    16. columns: [
    17. {
    18. title: 'Date',
    19. dataIndex: 'date',
    20. width: 200,
    21. },
    22. {
    23. title: 'Amount',
    24. dataIndex: 'amount',
    25. width: 100,
    26. },
    27. {
    28. title: 'Type',
    29. dataIndex: 'type',
    30. width: 100,
    31. },
    32. {
    33. title: 'Note',
    34. dataIndex: 'note',
    35. width: 100,
    36. },
    37. {
    38. title: 'Action',
    39. key: 'action',
    40. render: () => <a href="javascript:;">Delete</a>,
    41. },
    42. ],
    43. };
    44. components = {
    45. header: {
    46. cell: ResizeableTitle,
    47. },
    48. };
    49. data = [
    50. {
    51. key: 0,
    52. date: '2018-02-11',
    53. amount: 120,
    54. type: 'income',
    55. note: 'transfer',
    56. },
    57. {
    58. key: 1,
    59. date: '2018-03-11',
    60. amount: 243,
    61. type: 'income',
    62. note: 'transfer',
    63. },
    64. {
    65. key: 2,
    66. date: '2018-04-11',
    67. amount: 98,
    68. type: 'income',
    69. note: 'transfer',
    70. },
    71. ];
    72. handleResize = index => (e, { size }) => {
    73. this.setState(({ columns }) => {
    74. const nextColumns = [...columns];
    75. nextColumns[index] = {
    76. ...nextColumns[index],
    77. width: size.width,
    78. };
    79. return { columns: nextColumns };
    80. });
    81. };
    82. render() {
    83. const columns = this.state.columns.map((col, index) => ({
    84. ...col,
    85. onHeaderCell: column => ({
    86. width: column.width,
    87. onResize: this.handleResize(index),
    88. }),
    89. }));
    90. return <Table bordered components={this.components} columns={columns} dataSource={this.data} />;
    91. }
    92. }
    93. ReactDOM.render(<Demo />, mountNode);
    1. #components-table-demo-resizable-column .react-resizable {
    2. position: relative;
    3. }
    4. #components-table-demo-resizable-column .react-resizable-handle {
    5. position: absolute;
    6. width: 10px;
    7. height: 100%;
    8. bottom: 0;
    9. right: -5px;
    10. cursor: col-resize;
    11. }

    Table 表格 - 图24

    动态控制表格属性

    选择不同配置组合查看效果。

    1. import { Table, Icon, Switch, Radio, Form, Divider } from 'antd';
    2. const FormItem = Form.Item;
    3. const columns = [
    4. {
    5. title: 'Name',
    6. dataIndex: 'name',
    7. key: 'name',
    8. width: 150,
    9. render: text => <a href="javascript:;">{text}</a>,
    10. },
    11. {
    12. title: 'Age',
    13. dataIndex: 'age',
    14. key: 'age',
    15. width: 70,
    16. },
    17. {
    18. title: 'Address',
    19. dataIndex: 'address',
    20. key: 'address',
    21. },
    22. {
    23. title: 'Action',
    24. key: 'action',
    25. width: 360,
    26. render: (text, record) => (
    27. <span>
    28. <a href="javascript:;">Action {record.name}</a>
    29. <Divider type="vertical" />
    30. <a href="javascript:;">Delete</a>
    31. <Divider type="vertical" />
    32. <a href="javascript:;" className="ant-dropdown-link">
    33. More actions <Icon type="down" />
    34. </a>
    35. </span>
    36. ),
    37. },
    38. ];
    39. const data = [];
    40. for (let i = 1; i <= 10; i++) {
    41. data.push({
    42. key: i,
    43. name: 'John Brown',
    44. age: `${i}2`,
    45. address: `New York No. ${i} Lake Park`,
    46. description: `My name is John Brown, I am ${i}2 years old, living in New York No. ${i} Lake Park.`,
    47. });
    48. }
    49. const expandedRowRender = record => <p>{record.description}</p>;
    50. const title = () => 'Here is title';
    51. const showHeader = true;
    52. const footer = () => 'Here is footer';
    53. const scroll = { y: 240 };
    54. const pagination = { position: 'bottom' };
    55. class Demo extends React.Component {
    56. state = {
    57. bordered: false,
    58. loading: false,
    59. pagination,
    60. size: 'default',
    61. expandedRowRender,
    62. title: undefined,
    63. showHeader,
    64. footer,
    65. rowSelection: {},
    66. scroll: undefined,
    67. hasData: true,
    68. };
    69. handleToggle = prop => enable => {
    70. this.setState({ [prop]: enable });
    71. };
    72. handleSizeChange = e => {
    73. this.setState({ size: e.target.value });
    74. };
    75. handleExpandChange = enable => {
    76. this.setState({ expandedRowRender: enable ? expandedRowRender : undefined });
    77. };
    78. handleTitleChange = enable => {
    79. this.setState({ title: enable ? title : undefined });
    80. };
    81. handleHeaderChange = enable => {
    82. this.setState({ showHeader: enable ? showHeader : false });
    83. };
    84. handleFooterChange = enable => {
    85. this.setState({ footer: enable ? footer : undefined });
    86. };
    87. handleRowSelectionChange = enable => {
    88. this.setState({ rowSelection: enable ? {} : undefined });
    89. };
    90. handleScollChange = enable => {
    91. this.setState({ scroll: enable ? scroll : undefined });
    92. };
    93. handleDataChange = hasData => {
    94. this.setState({ hasData });
    95. };
    96. handlePaginationChange = e => {
    97. const { value } = e.target;
    98. this.setState({
    99. pagination: value === 'none' ? false : { position: value },
    100. });
    101. };
    102. render() {
    103. const state = this.state;
    104. return (
    105. <div>
    106. <div className="components-table-demo-control-bar">
    107. <Form layout="inline">
    108. <FormItem label="Bordered">
    109. <Switch checked={state.bordered} onChange={this.handleToggle('bordered')} />
    110. </FormItem>
    111. <FormItem label="loading">
    112. <Switch checked={state.loading} onChange={this.handleToggle('loading')} />
    113. </FormItem>
    114. <FormItem label="Title">
    115. <Switch checked={!!state.title} onChange={this.handleTitleChange} />
    116. </FormItem>
    117. <FormItem label="Column Header">
    118. <Switch checked={!!state.showHeader} onChange={this.handleHeaderChange} />
    119. </FormItem>
    120. <FormItem label="Footer">
    121. <Switch checked={!!state.footer} onChange={this.handleFooterChange} />
    122. </FormItem>
    123. <FormItem label="Expandable">
    124. <Switch checked={!!state.expandedRowRender} onChange={this.handleExpandChange} />
    125. </FormItem>
    126. <FormItem label="Checkbox">
    127. <Switch checked={!!state.rowSelection} onChange={this.handleRowSelectionChange} />
    128. </FormItem>
    129. <FormItem label="Fixed Header">
    130. <Switch checked={!!state.scroll} onChange={this.handleScollChange} />
    131. </FormItem>
    132. <FormItem label="Has Data">
    133. <Switch checked={!!state.hasData} onChange={this.handleDataChange} />
    134. </FormItem>
    135. <FormItem label="Size">
    136. <Radio.Group size="default" value={state.size} onChange={this.handleSizeChange}>
    137. <Radio.Button value="default">Default</Radio.Button>
    138. <Radio.Button value="middle">Middle</Radio.Button>
    139. <Radio.Button value="small">Small</Radio.Button>
    140. </Radio.Group>
    141. </FormItem>
    142. <FormItem label="Pagination">
    143. <Radio.Group
    144. value={state.pagination ? state.pagination.position : 'none'}
    145. onChange={this.handlePaginationChange}
    146. >
    147. <Radio.Button value="top">Top</Radio.Button>
    148. <Radio.Button value="bottom">Bottom</Radio.Button>
    149. <Radio.Button value="both">Both</Radio.Button>
    150. <Radio.Button value="none">None</Radio.Button>
    151. </Radio.Group>
    152. </FormItem>
    153. </Form>
    154. </div>
    155. <Table {...this.state} columns={columns} dataSource={state.hasData ? data : null} />
    156. </div>
    157. );
    158. }
    159. }
    160. ReactDOM.render(<Demo />, mountNode);

    API

    Table

    参数说明类型默认值
    bordered是否展示外边框和列边框booleanfalse
    childrenColumnName指定树形结构的列名string[]children
    columns表格列的配置描述,具体项见下表ColumnProps[]-
    components覆盖默认的 table 元素TableComponents-
    dataSource数据数组any[]
    defaultExpandAllRows初始时,是否展开所有行booleanfalse
    defaultExpandedRowKeys默认展开的行string[]-
    expandedRowKeys展开的行,控制属性string[]-
    expandedRowRender额外的展开行Function(record, index, indent, expanded):ReactNode-
    expandIcon自定义展开图标,参考示例Function(props):ReactNode-
    expandRowByClick通过点击行来展开子行booleanfalse
    footer表格尾部Function(currentPageData)
    indentSize展示树形数据时,每层缩进的宽度,以 px 为单位number15
    loading页面是否加载中boolean|object (更多)false
    locale默认文案设置,目前包括排序、过滤、空数据文案objectfilterConfirm: '确定' filterReset: '重置' emptyText: '暂无数据' 默认值
    pagination分页器,参考配置项或 pagination 文档,设为 false 时不展示和进行分页object
    rowClassName表格行的类名Function(record, index):string-
    rowKey表格行 key 的取值,可以是字符串或一个函数string|Function(record):string'key'
    rowSelection表格行是否可选择,配置项objectnull
    scroll设置横向或纵向滚动,也可用于指定滚动区域的宽和高,可以设置为像素值,百分比,true 和 'max-content'{ x: number | true, y: number }-
    showHeader是否显示表头booleantrue
    size表格大小default | middle | smalldefault
    title表格标题Function(currentPageData)
    onChange分页、排序、筛选变化时触发Function(pagination, filters, sorter, extra: { currentDataSource: [] })
    onExpand点击展开图标时触发Function(expanded, record)
    onExpandedRowsChange展开的行变化时触发Function(expandedRows)
    onHeaderRow设置头部行属性Function(column, index)-
    onRow设置行属性Function(record, index)-

    onRow 用法

    适用于 onRow onHeaderRow onCell onHeaderCell

    1. <Table
    2. onRow={record => {
    3. return {
    4. onClick: event => {}, // 点击行
    5. onDoubleClick: event => {},
    6. onContextMenu: event => {},
    7. onMouseEnter: event => {}, // 鼠标移入行
    8. onMouseLeave: event => {},
    9. };
    10. }}
    11. onHeaderRow={column => {
    12. return {
    13. onClick: () => {}, // 点击表头行
    14. };
    15. }}
    16. />

    Column

    列描述数据对象,是 columns 中的一项,Column 使用相同的 API。

    参数说明类型默认值
    align设置列的对齐方式'left' | 'right' | 'center''left'
    className列样式类名string-
    colSpan表头列合并,设置为 0 时,不渲染number
    dataIndex列数据在数据项中对应的 key,支持 a.b.ca[0].b.c[1] 的嵌套写法string-
    defaultSortOrder默认排序顺序'ascend' | 'descend'-
    filterDropdown可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互ReactNode-
    filterDropdownVisible用于控制自定义筛选菜单是否可见boolean-
    filtered标识数据是否经过过滤,筛选图标会高亮booleanfalse
    filteredValue筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组string[]-
    filterIcon自定义 filter 图标。ReactNode|(filtered: boolean) => ReactNodefalse
    filterMultiple是否多选booleantrue
    filters表头的筛选菜单项object[]-
    fixed列是否固定,可选 true(等效于 left) 'left' 'right'boolean|stringfalse
    keyReact 需要的 key,如果已经设置了唯一的 dataIndex,可以忽略这个属性string-
    render生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并Function(text, record, index) {}-
    sorter排序函数,本地排序使用一个函数(参考 Array.sort 的 compareFunction),需要服务端排序可设为 trueFunction|boolean-
    sortOrder排序的受控属性,外界可用此控制列的排序,可设置为 'ascend' 'descend' falseboolean|string-
    sortDirections支持的排序方式,取值为 'ascend' 'descend'Array['ascend', 'descend']
    title列头显示文字ReactNode|({ sortOrder, filters }) => ReactNode-
    width列宽度(指定了也不生效?)string|number-
    onCell设置单元格属性Function(record, rowIndex)-
    onFilter本地模式下,确定筛选的运行函数Function-
    onFilterDropdownVisibleChange自定义筛选菜单可见变化时调用function(visible) {}-
    onHeaderCell设置头部单元格属性Function(column)-

    ColumnGroup

    参数说明类型默认值
    title列头显示文字string|ReactNode-

    pagination

    分页的配置项。

    参数说明类型默认值
    position指定分页显示的位置'top' | 'bottom' | 'both''bottom'

    更多配置项,请查看 Pagination

    rowSelection

    选择功能的配置。

    参数说明类型默认值
    columnWidth自定义列表选择框宽度string|number60px
    columnTitle自定义列表选择框标题string|React.ReactNode-
    fixed把选择框列固定在左边boolean-
    getCheckboxProps选择框的默认属性配置Function(record)-
    hideDefaultSelections去掉『全选』『反选』两个默认选项booleanfalse
    selectedRowKeys指定选中项的 key 数组,需要和 onChange 进行配合string[][]
    selections自定义选择项 配置项, 设为 true 时使用默认选择项object[]|booleantrue
    type多选/单选,checkbox or radiostringcheckbox
    onChange选中项发生变化时的回调Function(selectedRowKeys, selectedRows)-
    onSelect用户手动选择/取消选择某行的回调Function(record, selected, selectedRows, nativeEvent)-
    onSelectAll用户手动选择/取消选择所有行的回调Function(selected, selectedRows, changeRows)-
    onSelectInvert用户手动选择反选的回调Function(selectedRows)-

    selection

    参数说明类型默认值
    keyReact 需要的 key,建议设置string-
    text选择项显示的文字string|React.ReactNode-
    onSelect选择项点击回调Function(changeableRowKeys)-

    在 TypeScript 中使用

    1. import { Table } from 'antd';
    2. import { ColumnProps } from 'antd/lib/table';
    3. interface IUser {
    4. key: number;
    5. name: string;
    6. }
    7. const columns: ColumnProps<IUser>[] = [{
    8. key: 'name',
    9. title: 'Name',
    10. dataIndex: 'name',
    11. }];
    12. const data: IUser[] = [{
    13. key: 0,
    14. name: 'Jack',
    15. }];
    16. class UserTable extends Table<IUser> {}
    17. <UserTable columns={columns} dataSource={data} />
    18. // 使用 JSX 风格的 API
    19. class NameColumn extends Table.Column<IUser> {}
    20. <UserTable dataSource={data}>
    21. <NameColumn key="name" title="Name" dataIndex="name" />
    22. </UserTable>
    23. // TypeScript 2.9 之后也可以这样写
    24. // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#generic-type-arguments-in-jsx-elements
    25. <Table<IUser> columns={columns} dataSource={data} />
    26. <Table<IUser> dataSource={data}>
    27. <Table.Column<IUser> key="name" title="Name" dataIndex="name" />
    28. </Table>

    注意

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

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

    控制台警告

    1. // 比如你的数据主键是 uid
    2. return <Table rowKey="uid" />;
    3. // 或
    4. return <Table rowKey={record => record.uid} />;