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} />;