• Table 表格
    • 何时使用
    • 如何使用
    • 代码演示
      • 远程加载数据
      • 基本用法
      • 带边框
      • 表格行/列合并
      • 自定义筛选菜单
      • 可编辑单元格
      • 可编辑行
      • 树形数据展示
      • 可展开
      • 固定头和列
      • 固定列
      • 固定表头
      • 表头分组
      • 筛选和排序
      • 嵌套子表格
      • 可控的筛选和排序
      • 选择和操作
      • 自定义选择项
      • 可选择
      • 紧凑型
      • template 风格的 API
  • API
    • Table
    • 事件
      • customRow 用法
    • Column
    • ColumnGroup
    • pagination
    • rowSelection
    • selection
  • 注意

    Table 表格

    展示行列数据。

    何时使用

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

    如何使用

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

    代码演示

    Table表格 - 图1

    远程加载数据

    这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 onFiltersorter 函数,而是在把筛选和排序的参数发到服务端来处理。注意,此示例使用 模拟接口,展示数据可能不准确,请打开网络面板查看请求。

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

    Table表格 - 图2

    基本用法

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

    1. <template>
    2. <a-table :columns="columns" :dataSource="data">
    3. <a slot="name" slot-scope="text" href="javascript:;">{{text}}</a>
    4. <span slot="customTitle"><a-icon type="smile-o" /> Name</span>
    5. <span slot="tags" slot-scope="tags">
    6. <a-tag v-for="tag in tags" color="blue" :key="tag">{{tag}}</a-tag>
    7. </span>
    8. <span slot="action" slot-scope="text, record">
    9. <a href="javascript:;">Invite 一 {{record.name}}</a>
    10. <a-divider type="vertical" />
    11. <a href="javascript:;">Delete</a>
    12. <a-divider type="vertical" />
    13. <a href="javascript:;" class="ant-dropdown-link">
    14. More actions <a-icon type="down" />
    15. </a>
    16. </span>
    17. </a-table>
    18. </template>
    19. <script>
    20. const columns = [{
    21. dataIndex: 'name',
    22. key: 'name',
    23. slots: { title: 'customTitle' },
    24. scopedSlots: { customRender: 'name' },
    25. }, {
    26. title: 'Age',
    27. dataIndex: 'age',
    28. key: 'age',
    29. }, {
    30. title: 'Address',
    31. dataIndex: 'address',
    32. key: 'address',
    33. }, {
    34. title: 'Tags',
    35. key: 'tags',
    36. dataIndex: 'tags',
    37. scopedSlots: { customRender: 'tags' },
    38. }, {
    39. title: 'Action',
    40. key: 'action',
    41. scopedSlots: { customRender: 'action' },
    42. }];
    43. const data = [{
    44. key: '1',
    45. name: 'John Brown',
    46. age: 32,
    47. address: 'New York No. 1 Lake Park',
    48. tags: ['nice', 'developer'],
    49. }, {
    50. key: '2',
    51. name: 'Jim Green',
    52. age: 42,
    53. address: 'London No. 1 Lake Park',
    54. tags: ['loser'],
    55. }, {
    56. key: '3',
    57. name: 'Joe Black',
    58. age: 32,
    59. address: 'Sidney No. 1 Lake Park',
    60. tags: ['cool', 'teacher'],
    61. }];
    62. export default {
    63. data() {
    64. return {
    65. data,
    66. columns,
    67. }
    68. }
    69. }
    70. </script>

    Table表格 - 图3

    带边框

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

    1. <template>
    2. <a-table :columns="columns" :dataSource="data" bordered>
    3. <template slot="name" slot-scope="text">
    4. <a href="javascript:;">{{text}}</a>
    5. </template>
    6. <template slot="title" slot-scope="currentPageData">
    7. Header
    8. </template>
    9. <template slot="footer" slot-scope="currentPageData">
    10. Footer
    11. </template>
    12. </a-table>
    13. </template>
    14. <script>
    15. const columns = [{
    16. title: 'Name',
    17. dataIndex: 'name',
    18. scopedSlots: { customRender: 'name' },
    19. }, {
    20. title: 'Cash Assets',
    21. className: 'column-money',
    22. dataIndex: 'money',
    23. }, {
    24. title: 'Address',
    25. dataIndex: 'address',
    26. }];
    27. const data = [{
    28. key: '1',
    29. name: 'John Brown',
    30. money: '¥300,000.00',
    31. address: 'New York No. 1 Lake Park',
    32. }, {
    33. key: '2',
    34. name: 'Jim Green',
    35. money: '¥1,256,000.00',
    36. address: 'London No. 1 Lake Park',
    37. }, {
    38. key: '3',
    39. name: 'Joe Black',
    40. money: '¥120,000.00',
    41. address: 'Sidney No. 1 Lake Park',
    42. }];
    43. export default {
    44. data() {
    45. return {
    46. data,
    47. columns,
    48. }
    49. }
    50. }
    51. </script>
    52. <style>
    53. th.column-money,
    54. td.column-money {
    55. text-align: right !important;
    56. }
    57. </style>

    Table表格 - 图4

    表格行/列合并

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

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

    Table表格 - 图5

    自定义筛选菜单

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

    1. <template>
    2. <a-table :dataSource="data" :columns="columns">
    3. <div slot="filterDropdown" slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }" class='custom-filter-dropdown'>
    4. <a-input
    5. v-ant-ref="c => searchInput = c"
    6. :placeholder="`Search ${column.dataIndex}`"
    7. :value="selectedKeys[0]"
    8. @change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
    9. @pressEnter="() => handleSearch(selectedKeys, confirm)"
    10. style="width: 188px; margin-bottom: 8px; display: block;"
    11. />
    12. <a-button
    13. type='primary'
    14. @click="() => handleSearch(selectedKeys, confirm)"
    15. icon="search"
    16. size="small"
    17. style="width: 90px; margin-right: 8px"
    18. >Search</a-button>
    19. <a-button
    20. @click="() => handleReset(clearFilters)"
    21. size="small"
    22. style="width: 90px"
    23. >Reset</a-button>
    24. </div>
    25. <a-icon slot="filterIcon" slot-scope="filtered" type='search' :style="{ color: filtered ? '#108ee9' : undefined }" />
    26. <template slot="customRender" slot-scope="text">
    27. <span v-if="searchText">
    28. <template v-for="(fragment, i) in text.toString().split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i'))">
    29. <mark v-if="fragment.toLowerCase() === searchText.toLowerCase()" :key="i" class="highlight">{{fragment}}</mark>
    30. <template v-else>{{fragment}}</template>
    31. </template>
    32. </span>
    33. <template v-else>{{text}}</template>
    34. </template>
    35. </a-table>
    36. </template>
    37. <script>
    38. const data = [{
    39. key: '1',
    40. name: 'John Brown',
    41. age: 32,
    42. address: 'New York No. 1 Lake Park',
    43. }, {
    44. key: '2',
    45. name: 'Joe Black',
    46. age: 42,
    47. address: 'London No. 1 Lake Park',
    48. }, {
    49. key: '3',
    50. name: 'Jim Green',
    51. age: 32,
    52. address: 'Sidney No. 1 Lake Park',
    53. }, {
    54. key: '4',
    55. name: 'Jim Red',
    56. age: 32,
    57. address: 'London No. 2 Lake Park',
    58. }]
    59. export default {
    60. data () {
    61. return {
    62. data,
    63. searchText: '',
    64. searchInput: null,
    65. columns: [{
    66. title: 'Name',
    67. dataIndex: 'name',
    68. key: 'name',
    69. scopedSlots: {
    70. filterDropdown: 'filterDropdown',
    71. filterIcon: 'filterIcon',
    72. customRender: 'customRender',
    73. },
    74. onFilter: (value, record) => record.name.toLowerCase().includes(value.toLowerCase()),
    75. onFilterDropdownVisibleChange: (visible) => {
    76. if (visible) {
    77. setTimeout(() => {
    78. this.searchInput.focus()
    79. },0)
    80. }
    81. },
    82. }, {
    83. title: 'Age',
    84. dataIndex: 'age',
    85. key: 'age',
    86. scopedSlots: {
    87. filterDropdown: 'filterDropdown',
    88. filterIcon: 'filterIcon',
    89. customRender: 'customRender',
    90. },
    91. onFilter: (value, record) => record.age.toLowerCase().includes(value.toLowerCase()),
    92. onFilterDropdownVisibleChange: (visible) => {
    93. if (visible) {
    94. setTimeout(() => {
    95. this.searchInput.focus()
    96. })
    97. }
    98. },
    99. }, {
    100. title: 'Address',
    101. dataIndex: 'address',
    102. key: 'address',
    103. scopedSlots: {
    104. filterDropdown: 'filterDropdown',
    105. filterIcon: 'filterIcon',
    106. customRender: 'customRender',
    107. },
    108. onFilter: (value, record) => record.address.toLowerCase().includes(value.toLowerCase()),
    109. onFilterDropdownVisibleChange: (visible) => {
    110. if (visible) {
    111. setTimeout(() => {
    112. this.searchInput.focus()
    113. })
    114. }
    115. },
    116. }],
    117. }
    118. },
    119. methods: {
    120. handleSearch (selectedKeys, confirm) {
    121. confirm()
    122. this.searchText = selectedKeys[0]
    123. },
    124. handleReset (clearFilters) {
    125. clearFilters()
    126. this.searchText = ''
    127. },
    128. },
    129. }
    130. </script>
    131. <style scoped>
    132. .custom-filter-dropdown {
    133. padding: 8px;
    134. border-radius: 4px;
    135. background: #fff;
    136. box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
    137. }
    138. .highlight {
    139. background-color: rgb(255, 192, 105);
    140. padding: 0px;
    141. }
    142. </style>

    Table表格 - 图6

    可编辑单元格

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

    1. <template>
    2. <div>
    3. <a-button class="editable-add-btn" @click="handleAdd">Add</a-button>
    4. <a-table bordered :dataSource="dataSource" :columns="columns">
    5. <template slot="name" slot-scope="text, record">
    6. <editable-cell :text="text" @change="onCellChange(record.key, 'name', $event)"/>
    7. </template>
    8. <template slot="operation" slot-scope="text, record">
    9. <a-popconfirm
    10. v-if="dataSource.length"
    11. title="Sure to delete?"
    12. @confirm="() => onDelete(record.key)">
    13. <a href="javascript:;">Delete</a>
    14. </a-popconfirm>
    15. </template>
    16. </a-table>
    17. </div>
    18. </template>
    19. <script>
    20. import EditableCell from './EditableCell'
    21. /*
    22. * EditableCell Code https://github.com/vueComponent/ant-design-vue/blob/master/components/table/demo/EditableCell.vue
    23. */
    24. export default {
    25. components: {
    26. EditableCell,
    27. },
    28. data () {
    29. return {
    30. dataSource: [{
    31. key: '0',
    32. name: 'Edward King 0',
    33. age: '32',
    34. address: 'London, Park Lane no. 0',
    35. }, {
    36. key: '1',
    37. name: 'Edward King 1',
    38. age: '32',
    39. address: 'London, Park Lane no. 1',
    40. }],
    41. count: 2,
    42. columns: [{
    43. title: 'name',
    44. dataIndex: 'name',
    45. width: '30%',
    46. scopedSlots: { customRender: 'name' },
    47. }, {
    48. title: 'age',
    49. dataIndex: 'age',
    50. }, {
    51. title: 'address',
    52. dataIndex: 'address',
    53. }, {
    54. title: 'operation',
    55. dataIndex: 'operation',
    56. scopedSlots: { customRender: 'operation' },
    57. }],
    58. }
    59. },
    60. methods: {
    61. onCellChange (key, dataIndex, value) {
    62. const dataSource = [...this.dataSource]
    63. const target = dataSource.find(item => item.key === key)
    64. if (target) {
    65. target[dataIndex] = value
    66. this.dataSource = dataSource
    67. }
    68. },
    69. onDelete (key) {
    70. const dataSource = [...this.dataSource]
    71. this.dataSource = dataSource.filter(item => item.key !== key)
    72. },
    73. handleAdd () {
    74. const { count, dataSource } = this
    75. const newData = {
    76. key: count,
    77. name: `Edward King ${count}`,
    78. age: 32,
    79. address: `London, Park Lane no. ${count}`,
    80. }
    81. this.dataSource = [...dataSource, newData]
    82. this.count = count + 1
    83. },
    84. },
    85. }
    86. </script>
    87. <style>
    88. .editable-cell {
    89. position: relative;
    90. }
    91. .editable-cell-input-wrapper,
    92. .editable-cell-text-wrapper {
    93. padding-right: 24px;
    94. }
    95. .editable-cell-text-wrapper {
    96. padding: 5px 24px 5px 5px;
    97. }
    98. .editable-cell-icon,
    99. .editable-cell-icon-check {
    100. position: absolute;
    101. right: 0;
    102. width: 20px;
    103. cursor: pointer;
    104. }
    105. .editable-cell-icon {
    106. line-height: 18px;
    107. display: none;
    108. }
    109. .editable-cell-icon-check {
    110. line-height: 28px;
    111. }
    112. .editable-cell:hover .editable-cell-icon {
    113. display: inline-block;
    114. }
    115. .editable-cell-icon:hover,
    116. .editable-cell-icon-check:hover {
    117. color: #108ee9;
    118. }
    119. .editable-add-btn {
    120. margin-bottom: 8px;
    121. }
    122. </style>

    Table表格 - 图7

    可编辑行

    带行编辑功能的表格。

    1. <template>
    2. <a-table :columns="columns" :dataSource="data" bordered>
    3. <template v-for="col in ['name', 'age', 'address']" :slot="col" slot-scope="text, record, index">
    4. <div :key="col">
    5. <a-input
    6. v-if="record.editable"
    7. style="margin: -5px 0"
    8. :value="text"
    9. @change="e => handleChange(e.target.value, record.key, col)"
    10. />
    11. <template v-else>{{text}}</template>
    12. </div>
    13. </template>
    14. <template slot="operation" slot-scope="text, record, index">
    15. <div class='editable-row-operations'>
    16. <span v-if="record.editable">
    17. <a @click="() => save(record.key)">Save</a>
    18. <a-popconfirm title='Sure to cancel?' @confirm="() => cancel(record.key)">
    19. <a>Cancel</a>
    20. </a-popconfirm>
    21. </span>
    22. <span v-else>
    23. <a @click="() => edit(record.key)">Edit</a>
    24. </span>
    25. </div>
    26. </template>
    27. </a-table>
    28. </template>
    29. <script>
    30. const columns = [{
    31. title: 'name',
    32. dataIndex: 'name',
    33. width: '25%',
    34. scopedSlots: { customRender: 'name' },
    35. }, {
    36. title: 'age',
    37. dataIndex: 'age',
    38. width: '15%',
    39. scopedSlots: { customRender: 'age' },
    40. }, {
    41. title: 'address',
    42. dataIndex: 'address',
    43. width: '40%',
    44. scopedSlots: { customRender: 'address' },
    45. }, {
    46. title: 'operation',
    47. dataIndex: 'operation',
    48. scopedSlots: { customRender: 'operation' },
    49. }]
    50. const data = []
    51. for (let i = 0; i < 100; i++) {
    52. data.push({
    53. key: i.toString(),
    54. name: `Edrward ${i}`,
    55. age: 32,
    56. address: `London Park no. ${i}`,
    57. })
    58. }
    59. export default {
    60. data () {
    61. this.cacheData = data.map(item => ({ ...item }))
    62. return {
    63. data,
    64. columns,
    65. }
    66. },
    67. methods: {
    68. handleChange (value, key, column) {
    69. const newData = [...this.data]
    70. const target = newData.filter(item => key === item.key)[0]
    71. if (target) {
    72. target[column] = value
    73. this.data = newData
    74. }
    75. },
    76. edit (key) {
    77. const newData = [...this.data]
    78. const target = newData.filter(item => key === item.key)[0]
    79. if (target) {
    80. target.editable = true
    81. this.data = newData
    82. }
    83. },
    84. save (key) {
    85. const newData = [...this.data]
    86. const target = newData.filter(item => key === item.key)[0]
    87. if (target) {
    88. delete target.editable
    89. this.data = newData
    90. this.cacheData = newData.map(item => ({ ...item }))
    91. }
    92. },
    93. cancel (key) {
    94. const newData = [...this.data]
    95. const target = newData.filter(item => key === item.key)[0]
    96. if (target) {
    97. Object.assign(target, this.cacheData.filter(item => key === item.key)[0])
    98. delete target.editable
    99. this.data = newData
    100. }
    101. },
    102. },
    103. }
    104. </script>
    105. <style scoped>
    106. .editable-row-operations a {
    107. margin-right: 8px;
    108. }
    109. </style>

    Table表格 - 图8

    树形数据展示

    表格支持树形数据的展示,当数据中有 children 字段时会自动展示为树形表格,如果不需要或配置为其他字段可以用 childrenColumnName 进行配置。可以通过设置 indentSize 以控制每一层的缩进宽度。

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

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

    Table表格 - 图9

    可展开

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

    1. <template>
    2. <a-table :columns="columns" :dataSource="data">
    3. <a slot="action" slot-scope="text" href="javascript:;">Delete</a>
    4. <p slot="expandedRowRender" slot-scope="record" style="margin: 0">{{record.description}}</p>
    5. </a-table>
    6. </template>
    7. <script>
    8. const columns = [
    9. { title: 'Name', dataIndex: 'name', key: 'name' },
    10. { title: 'Age', dataIndex: 'age', key: 'age' },
    11. { title: 'Address', dataIndex: 'address', key: 'address' },
    12. { title: 'Action', dataIndex: '', key: 'x', scopedSlots: { customRender: 'action' } },
    13. ];
    14. const data = [
    15. { key: 1, name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.' },
    16. { key: 2, name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.' },
    17. { key: 3, name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.' },
    18. ];
    19. export default {
    20. data() {
    21. return {
    22. data,
    23. columns,
    24. }
    25. }
    26. }
    27. </script>

    Table表格 - 图10

    固定头和列

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

    若列头与内容不对齐或出现列重复,请指定列的宽度 width。建议指定 scroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 scroll.x

    <template>
      <a-table :columns="columns" :dataSource="data" :scroll="{ x: 1500, y: 300 }">
        <a slot="action" slot-scope="text" href="javascript:;">action</a>
      </a-table>
    </template>
    <script>
    const columns = [
      { title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
      { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
      { title: 'Column 1', dataIndex: 'address', key: '1', width: 150 },
      { title: 'Column 2', dataIndex: 'address', key: '2', width: 150 },
      { title: 'Column 3', dataIndex: 'address', key: '3', width: 150 },
      { title: 'Column 4', dataIndex: 'address', key: '4', width: 150 },
      { title: 'Column 5', dataIndex: 'address', key: '5', width: 150 },
      { title: 'Column 6', dataIndex: 'address', key: '6', width: 150 },
      { title: 'Column 7', dataIndex: 'address', key: '7', width: 150 },
      { title: 'Column 8', dataIndex: 'address', key: '8' },
      {
        title: 'Action',
        key: 'operation',
        fixed: 'right',
        width: 100,
        scopedSlots: { customRender: 'action' },
      },
    ];
    
    const data = [];
    for (let i = 0; i < 100; i++) {
      data.push({
        key: i,
        name: `Edrward ${i}`,
        age: 32,
        address: `London Park no. ${i}`,
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      }
    }
    </script>
    

    Table表格 - 图11

    固定列

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

    若列头与内容不对齐或出现列重复,请指定列的宽度 width。建议指定 scroll.x 为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过 scroll.x

    <template>
      <a-table :columns="columns" :dataSource="data" :scroll="{ x: 1300 }">
        <a slot="action" slot-scope="text" href="javascript:;">action</a>
      </a-table>
    </template>
    <script>
    const columns = [
      { title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
      { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
      { title: 'Column 1', dataIndex: 'address', key: '1' },
      { title: 'Column 2', dataIndex: 'address', key: '2' },
      { title: 'Column 3', dataIndex: 'address', key: '3' },
      { title: 'Column 4', dataIndex: 'address', key: '4' },
      { title: 'Column 5', dataIndex: 'address', key: '5' },
      { title: 'Column 6', dataIndex: 'address', key: '6' },
      { title: 'Column 7', dataIndex: 'address', key: '7' },
      { title: 'Column 8', dataIndex: 'address', key: '8' },
      {
        title: 'Action',
        key: 'operation',
        fixed: 'right',
        width: 100,
        scopedSlots: { customRender: 'action' },
      },
    ];
    
    const data = [{
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York Park',
    }, {
      key: '2',
      name: 'Jim Green',
      age: 40,
      address: 'London Park',
    }];
    
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      }
    }
    </script>
    

    Table表格 - 图12

    固定表头

    方便一页内展示大量数据。需要指定 column 的 width 属性,否则列头和内容可能不对齐。

    <template>
      <a-table :columns="columns" :dataSource="data" :pagination="{ pageSize: 50 }" :scroll="{ y: 240 }" />
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
      width: 150,
    }, {
      title: 'Age',
      dataIndex: 'age',
      width: 150,
    }, {
      title: 'Address',
      dataIndex: 'address',
    }];
    
    const data = [];
    for (let i = 0; i < 100; i++) {
      data.push({
        key: i,
        name: `Edward King ${i}`,
        age: 32,
        address: `London, Park Lane no. ${i}`,
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      }
    }
    </script>
    

    Table表格 - 图13

    表头分组

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

    <template>
      <a-table
        :columns="columns"
        :dataSource="data"
        bordered
        size="middle"
        :scroll="{ x: '130%', y: 240 }"
      />
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
      key: 'name',
      width: 100,
      fixed: 'left',
      filters: [{
        text: 'Joe',
        value: 'Joe',
      }, {
        text: 'John',
        value: 'John',
      }],
      onFilter: (value, record) => record.name.indexOf(value) === 0,
    }, {
      title: 'Other',
      children: [{
        title: 'Age',
        dataIndex: 'age',
        key: 'age',
        width: 200,
        sorter: (a, b) => a.age - b.age,
      }, {
        title: 'Address',
        children: [{
          title: 'Street',
          dataIndex: 'street',
          key: 'street',
          width: 200,
        }, {
          title: 'Block',
          children: [{
            title: 'Building',
            dataIndex: 'building',
            key: 'building',
            width: 100,
          }, {
            title: 'Door No.',
            dataIndex: 'number',
            key: 'number',
            width: 100,
          }],
        }],
      }],
    }, {
      title: 'Company',
      children: [{
        title: 'Company Address',
        dataIndex: 'companyAddress',
        key: 'companyAddress',
      }, {
        title: 'Company Name',
        dataIndex: 'companyName',
        key: 'companyName',
      }],
    }, {
      title: 'Gender',
      dataIndex: 'gender',
      key: 'gender',
      width: 80,
      fixed: 'right',
    }];
    
    const data = [];
    for (let i = 0; i < 100; i++) {
      data.push({
        key: i,
        name: 'John Brown',
        age: i + 1,
        street: 'Lake Park',
        building: 'C',
        number: 2035,
        companyAddress: 'Lake Street 42',
        companyName: 'SoftLake Co',
        gender: 'M',
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      }
    }
    </script>
    

    Table表格 - 图14

    筛选和排序

    对某一列数据进行筛选,使用列的 filters 属性来指定需要筛选菜单的列,onFilter 用于筛选当前数据,filterMultiple 用于指定多选和单选。对某一列数据进行排序,通过指定列的 sorter 函数即可启动排序按钮。sorter: function(rowA, rowB) { … }, rowA、rowB 为比较的两个行数据。使用 defaultSortOrder 属性,设置列的默认排序顺序。

    <template>
      <a-table :columns="columns" :dataSource="data" @change="onChange"/>
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
      filters: [{
        text: 'Joe',
        value: 'Joe',
      }, {
        text: 'Jim',
        value: 'Jim',
      }, {
        text: 'Submenu',
        value: 'Submenu',
        children: [{
          text: 'Green',
          value: 'Green',
        }, {
          text: 'Black',
          value: 'Black',
        }],
      }],
      // specify the condition of filtering result
      // here is that finding the name started with `value`
      onFilter: (value, record) => record.name.indexOf(value) === 0,
      sorter: (a, b) => a.name.length - b.name.length,
    }, {
      title: 'Age',
      dataIndex: 'age',
      sorter: (a, b) => a.age - b.age,
    }, {
      title: 'Address',
      dataIndex: 'address',
      filters: [{
        text: 'London',
        value: 'London',
      }, {
        text: 'New York',
        value: 'New York',
      }],
      filterMultiple: false,
      onFilter: (value, record) => record.address.indexOf(value) === 0,
      sorter: (a, b) => a.address.length - b.address.length,
    }];
    
    const data = [{
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
    }, {
      key: '2',
      name: 'Jim Green',
      age: 42,
      address: 'London No. 1 Lake Park',
    }, {
      key: '3',
      name: 'Joe Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
    }, {
      key: '4',
      name: 'Jim Red',
      age: 32,
      address: 'London No. 2 Lake Park',
    }];
    
    function onChange(pagination, filters, sorter) {
      console.log('params', pagination, filters, sorter);
    }
    
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      },
      methods: {
        onChange,
      }
    }
    </script>
    

    Table表格 - 图15

    嵌套子表格

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

    <template>
      <a-table :columns="columns" :dataSource="data" class="components-table-demo-nested">
        <a slot="operation" slot-scope="text" href="javascript:;">Publish</a>
        <a-table
          slot="expandedRowRender"
          slot-scope="text"
          :columns="innerColumns"
          :dataSource="innerData"
          :pagination="false"
        >
          <span slot="status" slot-scope="text">
            <a-badge status="success" />Finished
          </span>
          <span slot="operation" slot-scope="text" class="table-operation">
            <a href="javascript:;">Pause</a>
            <a href="javascript:;">Stop</a>
            <a-dropdown>
              <a-menu slot="overlay">
                <a-menu-item>
                  Action 1
                </a-menu-item>
                <a-menu-item>
                  Action 2
                </a-menu-item>
              </a-menu>
              <a href="javascript:;">
                More <a-icon type="down" />
              </a>
            </a-dropdown>
          </span>
        </a-table>
      </a-table>
    </template>
    <script>
    const columns = [
      { title: 'Name', dataIndex: 'name', key: 'name' },
      { title: 'Platform', dataIndex: 'platform', key: 'platform' },
      { title: 'Version', dataIndex: 'version', key: 'version' },
      { title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
      { title: 'Creator', dataIndex: 'creator', key: 'creator' },
      { title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
      { title: 'Action', key: 'operation', scopedSlots: { customRender: 'operation' } },
    ];
    
    const data = [];
    for (let i = 0; i < 3; ++i) {
      data.push({
        key: i,
        name: 'Screem',
        platform: 'iOS',
        version: '10.3.4.5654',
        upgradeNum: 500,
        creator: 'Jack',
        createdAt: '2014-12-24 23:12:00',
      });
    }
    
    const innerColumns = [
      { title: 'Date', dataIndex: 'date', key: 'date' },
      { title: 'Name', dataIndex: 'name', key: 'name' },
      { title: 'Status', key: 'state', scopedSlots: { customRender: 'status' } },
      { title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
      {
        title: 'Action',
        dataIndex: 'operation',
        key: 'operation',
        scopedSlots: { customRender: 'operation' },
      },
    ];
    
    const innerData = [];
    for (let i = 0; i < 3; ++i) {
      innerData.push({
        key: i,
        date: '2014-12-24 23:12:00',
        name: 'This is production name',
        upgradeNum: 'Upgraded: 56',
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
          innerColumns,
          innerData,
        }
      }
    }
    </script>
    

    Table表格 - 图16

    可控的筛选和排序

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

    1. columns 中定义了 filteredValue 和 sortOrder 属性即视为受控模式。
    2. 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。
    3. 务必指定 column.key
    <template>
      <div>
        <div class="table-operations">
          <a-button @click="setAgeSort">Sort age</a-button>
          <a-button @click="clearFilters">Clear filters</a-button>
          <a-button @click="clearAll">Clear filters and sorters</a-button>
        </div>
        <a-table :columns="columns" :dataSource="data" @change="handleChange" />
      </div>
    </template>
    <script>
    const data = [{
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
    }, {
      key: '2',
      name: 'Jim Green',
      age: 42,
      address: 'London No. 1 Lake Park',
    }, {
      key: '3',
      name: 'Joe Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
    }, {
      key: '4',
      name: 'Jim Red',
      age: 32,
      address: 'London No. 2 Lake Park',
    }];
    
    export default {
      data() {
        return {
          data,
          filteredInfo: null,
          sortedInfo: null,
        }
      },
      computed: {
        columns() {
          let { sortedInfo, filteredInfo } = this;
          sortedInfo = sortedInfo || {};
          filteredInfo = filteredInfo || {};
          const columns = [{
            title: 'Name',
            dataIndex: 'name',
            key: 'name',
            filters: [
              { text: 'Joe', value: 'Joe' },
              { text: 'Jim', value: 'Jim' },
            ],
            filteredValue: filteredInfo.name || null,
            onFilter: (value, record) => record.name.includes(value),
            sorter: (a, b) => a.name.length - b.name.length,
            sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
          }, {
            title: 'Age',
            dataIndex: 'age',
            key: 'age',
            sorter: (a, b) => a.age - b.age,
            sortOrder: sortedInfo.columnKey === 'age' && sortedInfo.order,
          }, {
            title: 'Address',
            dataIndex: 'address',
            key: 'address',
            filters: [
              { text: 'London', value: 'London' },
              { text: 'New York', value: 'New York' },
            ],
            filteredValue: filteredInfo.address || null,
            onFilter: (value, record) => record.address.includes(value),
            sorter: (a, b) => a.address.length - b.address.length,
            sortOrder: sortedInfo.columnKey === 'address' && sortedInfo.order,
          }];
          return columns;
        }
      },
      methods: {
        handleChange (pagination, filters, sorter) {
          console.log('Various parameters', pagination, filters, sorter);
          this.filteredInfo = filters;
          this.sortedInfo = sorter;
        },
        clearFilters () {
          this.filteredInfo = null;
        },
        clearAll () {
          this.filteredInfo = null;
          this.sortedInfo = null;
        },
        setAgeSort () {
          this.sortedInfo = {
            order: 'descend',
            columnKey: 'age',
          }
        }
      }
    }
    </script>
    <style scoped>
    .table-operations {
      margin-bottom: 16px;
    }
    
    .table-operations > button {
      margin-right: 8px;
    }
    </style>
    

    Table表格 - 图17

    选择和操作

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

    <template>
      <div>
        <div style="margin-bottom: 16px">
          <a-button
            type="primary"
            @click="start"
            :disabled="!hasSelected"
            :loading="loading"
          >
            Reload
          </a-button>
          <span style="margin-left: 8px">
            <template v-if="hasSelected">
              {{`Selected ${selectedRowKeys.length} items`}}
            </template>
          </span>
        </div>
        <a-table :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" :columns="columns" :dataSource="data" />
      </div>
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
    }, {
      title: 'Age',
      dataIndex: 'age',
    }, {
      title: 'Address',
      dataIndex: 'address',
    }];
    
    const data = [];
    for (let i = 0; i < 46; i++) {
      data.push({
        key: i,
        name: `Edward King ${i}`,
        age: 32,
        address: `London, Park Lane no. ${i}`,
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
          selectedRowKeys: [], // Check here to configure the default column
          loading: false,
        }
      },
      computed: {
        hasSelected() {
          return this.selectedRowKeys.length > 0
        }
      },
      methods: {
        start () {
          this.loading = true;
          // ajax request after empty completing
          setTimeout(() => {
            this.loading = false;
            this.selectedRowKeys = [];
          }, 1000);
        },
        onSelectChange (selectedRowKeys) {
          console.log('selectedRowKeys changed: ', selectedRowKeys);
          this.selectedRowKeys = selectedRowKeys
        }
      },
    }
    </script>
    

    Table表格 - 图18

    自定义选择项

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

    <template>
      <a-table :rowSelection="rowSelection" :columns="columns" :dataSource="data" />
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
    }, {
      title: 'Age',
      dataIndex: 'age',
    }, {
      title: 'Address',
      dataIndex: 'address',
    }];
    
    const data = [];
    for (let i = 0; i < 46; i++) {
      data.push({
        key: i,
        name: `Edward King ${i}`,
        age: 32,
        address: `London, Park Lane no. ${i}`,
      });
    }
    
    export default {
      data() {
        return {
          data,
          columns,
          selectedRowKeys: [], // Check here to configure the default column
        }
      },
      computed: {
        rowSelection() {
          const { selectedRowKeys } = this;
          return {
            selectedRowKeys,
            onChange: this.onSelectChange,
            hideDefaultSelections: true,
            selections: [{
              key: 'all-data',
              text: 'Select All Data',
              onSelect: () => {
                this.selectedRowKeys = [...Array(46).keys()]; // 0...45
              },
            }, {
              key: 'odd',
              text: 'Select Odd Row',
              onSelect: (changableRowKeys) => {
                let newSelectedRowKeys = [];
                newSelectedRowKeys = changableRowKeys.filter((key, index) => {
                  if (index % 2 !== 0) {
                    return false;
                  }
                  return true;
                });
                this.selectedRowKeys = newSelectedRowKeys;
              },
            }, {
              key: 'even',
              text: 'Select Even Row',
              onSelect: (changableRowKeys) => {
                let newSelectedRowKeys = [];
                newSelectedRowKeys = changableRowKeys.filter((key, index) => {
                  if (index % 2 !== 0) {
                    return true;
                  }
                  return false;
                });
                this.selectedRowKeys = newSelectedRowKeys;
              },
            }],
            onSelection: this.onSelection,
          }
        }
      },
      methods: {
        onSelectChange (selectedRowKeys) {
          console.log('selectedRowKeys changed: ', selectedRowKeys);
          this.selectedRowKeys = selectedRowKeys
        },
      },
    }
    </script>
    

    Table表格 - 图19

    可选择

    第一列是联动的选择框。

    默认点击 checkbox 触发选择行为

    <template>
      <a-table :rowSelection="rowSelection" :columns="columns" :dataSource="data">
        <a slot="name" slot-scope="text" href="javascript:;">{{text}}</a>
      </a-table>
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
      scopedSlots: { customRender: 'name' },
    }, {
      title: 'Age',
      dataIndex: 'age',
    }, {
      title: 'Address',
      dataIndex: 'address',
    }];
    const data = [{
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
    }, {
      key: '2',
      name: 'Jim Green',
      age: 42,
      address: 'London No. 1 Lake Park',
    }, {
      key: '3',
      name: 'Joe Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
    }, {
      key: '4',
      name: 'Disabled User',
      age: 99,
      address: 'Sidney No. 1 Lake Park',
    }];
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      },
      computed: {
        rowSelection() {
          const { selectedRowKeys } = this;
          return {
            onChange: (selectedRowKeys, selectedRows) => {
              console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
            },
            getCheckboxProps: record => ({
              props: {
                disabled: record.name === 'Disabled User', // Column configuration not to be checked
                name: record.name,
              }
            }),
          }
        }
      },
    }
    </script>
    

    Table表格 - 图20

    紧凑型

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

    <template>
      <div id="components-table-demo-size">
        <h4>Middle size table</h4>
        <a-table :columns="columns" :dataSource="data" size="middle" />
        <h4>Small size table</h4>
        <a-table :columns="columns" :dataSource="data" size="small" />
      </div>
    </template>
    <script>
    const columns = [{
      title: 'Name',
      dataIndex: 'name',
    }, {
      title: 'Age',
      dataIndex: 'age',
    }, {
      title: 'Address',
      dataIndex: 'address',
    }];
    const data = [{
      key: '1',
      name: 'John Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
    }, {
      key: '2',
      name: 'Jim Green',
      age: 42,
      address: 'London No. 1 Lake Park',
    }, {
      key: '3',
      name: 'Joe Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
    }];
    
    export default {
      data() {
        return {
          data,
          columns,
        }
      }
    }
    </script>
    <style>
    #components-table-demo-size h4 { margin-bottom: 16px; }
    </style>
    

    Table表格 - 图21

    template 风格的 API

    使用 template 风格的 API

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

    <template>
      <a-table :dataSource="data">
        <a-table-column-group>
          <span slot="title" style="color: #1890ff">Name</span>
          <a-table-column
            dataIndex="firstName"
            key="firstName"
          >
            <span slot="title" style="color: #1890ff">First Name</span>
          </a-table-column>
          <a-table-column
            title="Last Name"
            dataIndex="lastName"
            key="lastName"
          />
        </a-table-column-group>
        <a-table-column
          title="Age"
          dataIndex="age"
          key="age"
        />
        <a-table-column
          title="Address"
          dataIndex="address"
          key="address"
        />
        <a-table-column
          title="Tags"
          dataIndex="tags"
          key="tags"
        >
          <template slot-scope="tags">
            <span>
              <a-tag v-for="tag in tags" color="blue" :key="tag">{{tag}}</a-tag>
            </span>
          </template>
        </a-table-column>
        <a-table-column
          title="Action"
          key="action"
        >
          <template slot-scope="text, record">
            <span>
              <a href="javascript:;">Action 一 {{record.firstName}}</a>
              <a-divider type="vertical" />
              <a href="javascript:;">Delete</a>
            </span>
          </template>
        </a-table-column>
      </a-table>
    </template>
    <script>
    
    const data = [{
      key: '1',
      firstName: 'John',
      lastName: 'Brown',
      age: 32,
      address: 'New York No. 1 Lake Park',
      tags: ['nice', 'developer'],
    }, {
      key: '2',
      firstName: 'Jim',
      lastName: 'Green',
      age: 42,
      address: 'London No. 1 Lake Park',
      tags: ['loser'],
    }, {
      key: '3',
      firstName: 'Joe',
      lastName: 'Black',
      age: 32,
      address: 'Sidney No. 1 Lake Park',
      tags: ['cool', 'teacher'],
    }];
    
    export default {
      data() {
        return {
          data,
        }
      }
    }
    </script>
    
    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} />
    

    API

    Table

    参数说明类型默认值
    bordered是否展示外边框和列边框booleanfalse
    childrenColumnName指定树形结构的列名string[]children
    columns表格列的配置描述,具体项见下表array-
    components覆盖默认的 table 元素object-
    dataSource数据数组any[]
    defaultExpandAllRows初始时,是否展开所有行booleanfalse
    defaultExpandedRowKeys默认展开的行string[]-
    expandedRowKeys展开的行,控制属性string[]-
    expandedRowRender额外的展开行Function(record, index, indent, expanded):VNode | slot="expandedRowRender" slot-scope="record, index, indent, expanded"-
    expandIcon自定义展开图标Function(props):VNode | slot="expandIcon" slot-scope="props"-
    expandRowByClick通过点击行来展开子行booleanfalse
    footer表格尾部Function(currentPageData)|slot-scope
    indentSize展示树形数据时,每层缩进的宽度,以 px 为单位number15
    loading页面是否加载中boolean|objectfalse
    locale默认文案设置,目前包括排序、过滤、空数据文案objectfilterConfirm: '确定' filterReset: '重置' emptyText: '暂无数据'
    pagination分页器,参考配置项或 pagination,设为 false 时不展示和进行分页object
    rowClassName表格行的类名Function(record, index):string-
    rowKey表格行 key 的取值,可以是字符串或一个函数string|Function(record):string'key'
    rowSelection列表项是否可选择,配置项objectnull
    scroll设置横向或纵向滚动,也可用于指定滚动区域的宽和高,建议为 x 设置一个数字,如果要设置为 true,需要配合样式 .ant-table td { white-space: nowrap; }{ x: number | true, y: number }-
    showHeader是否显示表头booleantrue
    size正常或迷你类型,default or smallstringdefault
    title表格标题Function(currentPageData)|slot-scope
    customHeaderRow设置头部行属性Function(column, index)-
    customRow设置行属性Function(record, index)-

    事件

    事件名称说明回调参数
    expandedRowsChange展开的行变化时触发Function(expandedRows)
    change分页、排序、筛选变化时触发Function(pagination, filters, sorter)
    expand点击展开图标时触发Function(expanded, record)

    customRow 用法

    适用于 customRow customHeaderRow customCell customHeaderCell。遵循Vue jsx语法。

    <Table
      customRow={(record) => {
        return {
          props: {
            xxx... //属性
          },
          on: { // 事件
            click: () => {},       // 点击行
            mouseenter: () => {},  // 鼠标移入行
            xxxx...
          },
    
        };
      )}
      customHeaderRow={(column) => {
        return {
          on: {
            click: () => {},        // 点击表头行
          }
        };
      )}
    />
    

    Column

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

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

    ColumnGroup

    参数说明类型默认值
    title列头显示文字string|slot-
    slots使用columns时,可以通过该属性配置支持slot的属性,如 slots: { title: 'XXX'}object-

    pagination

    分页的配置项。

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

    更多配置项,请查看 Pagination

    rowSelection

    选择功能的配置。

    参数说明类型默认值
    columnWidth自定义列表选择框宽度string|number-
    columnTitle自定义列表选择框标题string|VNode-
    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

    自定义选择配置项

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

    注意

    在 Table 中,dataSourcecolumns 里的数据值都需要指定 key 值。对于 dataSource 默认将每列数据的 key 属性作为唯一的标识。

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

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