Table表格 - 图1

Table 表格

展示行列数据。

设计师专属

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

何时使用

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

如何使用

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

  1. <template>
  2. <a-table :dataSource="dataSource" :columns="columns" />
  3. </template>
  4. <script>
  5. export default {
  6. setup() {
  7. return {
  8. dataSource: [
  9. {
  10. key: '1',
  11. name: '胡彦斌',
  12. age: 32,
  13. address: '西湖区湖底公园1号',
  14. },
  15. {
  16. key: '2',
  17. name: '胡彦祖',
  18. age: 42,
  19. address: '西湖区湖底公园1号',
  20. },
  21. ],
  22. columns: [
  23. {
  24. title: '姓名',
  25. dataIndex: 'name',
  26. key: 'name',
  27. },
  28. {
  29. title: '年龄',
  30. dataIndex: 'age',
  31. key: 'age',
  32. },
  33. {
  34. title: '住址',
  35. dataIndex: 'address',
  36. key: 'address',
  37. },
  38. ],
  39. };
  40. },
  41. };
  42. </script>

代码演示

Table表格 - 图2

基本用法

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data">
  3. <template #name="{ text }">
  4. <a>{{ text }}</a>
  5. </template>
  6. <template #customTitle>
  7. <span>
  8. <smile-outlined />
  9. Name
  10. </span>
  11. </template>
  12. <template #tags="{ text: tags }">
  13. <span>
  14. <a-tag
  15. v-for="tag in tags"
  16. :key="tag"
  17. :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
  18. >
  19. {{ tag.toUpperCase() }}
  20. </a-tag>
  21. </span>
  22. </template>
  23. <template #action="{ record }">
  24. <span>
  25. <a>Invite 一 {{ record.name }}</a>
  26. <a-divider type="vertical" />
  27. <a>Delete</a>
  28. <a-divider type="vertical" />
  29. <a class="ant-dropdown-link">
  30. More actions
  31. <down-outlined />
  32. </a>
  33. </span>
  34. </template>
  35. </a-table>
  36. </template>
  37. <script lang="ts">
  38. import { SmileOutlined, DownOutlined } from '@ant-design/icons-vue';
  39. import { defineComponent } from 'vue';
  40. const columns = [
  41. {
  42. dataIndex: 'name',
  43. key: 'name',
  44. slots: { title: 'customTitle', customRender: 'name' },
  45. },
  46. {
  47. title: 'Age',
  48. dataIndex: 'age',
  49. key: 'age',
  50. },
  51. {
  52. title: 'Address',
  53. dataIndex: 'address',
  54. key: 'address',
  55. },
  56. {
  57. title: 'Tags',
  58. key: 'tags',
  59. dataIndex: 'tags',
  60. slots: { customRender: 'tags' },
  61. },
  62. {
  63. title: 'Action',
  64. key: 'action',
  65. slots: { customRender: 'action' },
  66. },
  67. ];
  68. const data = [
  69. {
  70. key: '1',
  71. name: 'John Brown',
  72. age: 32,
  73. address: 'New York No. 1 Lake Park',
  74. tags: ['nice', 'developer'],
  75. },
  76. {
  77. key: '2',
  78. name: 'Jim Green',
  79. age: 42,
  80. address: 'London No. 1 Lake Park',
  81. tags: ['loser'],
  82. },
  83. {
  84. key: '3',
  85. name: 'Joe Black',
  86. age: 32,
  87. address: 'Sidney No. 1 Lake Park',
  88. tags: ['cool', 'teacher'],
  89. },
  90. ];
  91. export default defineComponent({
  92. setup() {
  93. return {
  94. data,
  95. columns,
  96. };
  97. },
  98. components: {
  99. SmileOutlined,
  100. DownOutlined,
  101. },
  102. });
  103. </script>

Table表格 - 图3

远程加载数据

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

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

  1. <template>
  2. <a-table
  3. :columns="columns"
  4. :row-key="record => record.login.uuid"
  5. :data-source="dataSource"
  6. :pagination="pagination"
  7. :loading="loading"
  8. @change="handleTableChange"
  9. >
  10. <template #name="{ text }">{{ text.first }} {{ text.last }}</template>
  11. </a-table>
  12. </template>
  13. <script lang="ts">
  14. import { TableState, TableStateFilters } from 'ant-design-vue/es/table/interface';
  15. import { useRequest } from 'vue-request';
  16. import axios from 'axios';
  17. import { defineComponent, reactive, UnwrapRef } from 'vue';
  18. const columns = [
  19. {
  20. title: 'Name',
  21. dataIndex: 'name',
  22. sorter: true,
  23. width: '20%',
  24. slots: { customRender: 'name' },
  25. },
  26. {
  27. title: 'Gender',
  28. dataIndex: 'gender',
  29. filters: [
  30. { text: 'Male', value: 'male' },
  31. { text: 'Female', value: 'female' },
  32. ],
  33. width: '20%',
  34. },
  35. {
  36. title: 'Email',
  37. dataIndex: 'email',
  38. },
  39. ];
  40. type Pagination = TableState['pagination'];
  41. type APIParams = {
  42. results: number;
  43. page?: number;
  44. sortField?: string;
  45. sortOrder?: number;
  46. [key: string]: any;
  47. };
  48. type APIResult = {
  49. results: {
  50. gender: 'female' | 'male';
  51. name: string;
  52. email: string;
  53. }[];
  54. };
  55. const queryData = (params: APIParams) => {
  56. return axios.get<APIResult>('https://randomuser.me/api', { params: params });
  57. };
  58. export default defineComponent({
  59. setup() {
  60. const pagination: UnwrapRef<Pagination> = reactive({ total: 200 });
  61. const { data: dataSource, run, loading } = useRequest(queryData, {
  62. defaultParams: [
  63. {
  64. results: 10,
  65. },
  66. ],
  67. formatResult: res => res.data.results,
  68. });
  69. const handleTableChange = (pag: Pagination, filters: TableStateFilters, sorter: any) => {
  70. console.log(pag);
  71. Object.assign(pagination, pag);
  72. run({
  73. results: pagination.pageSize!,
  74. page: pagination.current,
  75. sortField: sorter.field,
  76. sortOrder: sorter.order,
  77. ...filters,
  78. });
  79. };
  80. return {
  81. dataSource,
  82. pagination,
  83. loading,
  84. columns,
  85. handleTableChange,
  86. };
  87. },
  88. });
  89. </script>

Table表格 - 图4

带边框

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

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

Table表格 - 图5

单元格自动省略

设置 column.ellipsis 可以让单元格内容根据宽度自动省略。

列头缩略暂不支持和排序筛选一起使用。

  1. <template>
  2. <a-table :columns="columns" :data-source="data">
  3. <template #name="{ text }">
  4. <a>{{ text }}</a>
  5. </template>
  6. </a-table>
  7. </template>
  8. <script lang="ts">
  9. import { defineComponent } from 'vue';
  10. const columns = [
  11. {
  12. title: 'Name',
  13. dataIndex: 'name',
  14. key: 'name',
  15. slots: { customRender: 'name' },
  16. },
  17. {
  18. title: 'Age',
  19. dataIndex: 'age',
  20. key: 'age',
  21. width: 80,
  22. },
  23. {
  24. title: 'Address',
  25. dataIndex: 'address',
  26. key: 'address 1',
  27. ellipsis: true,
  28. },
  29. {
  30. title: 'Long Column Long Column Long Column',
  31. dataIndex: 'address',
  32. key: 'address 2',
  33. ellipsis: true,
  34. },
  35. {
  36. title: 'Long Column Long Column',
  37. dataIndex: 'address',
  38. key: 'address 3',
  39. ellipsis: true,
  40. },
  41. {
  42. title: 'Long Column',
  43. dataIndex: 'address',
  44. key: 'address 4',
  45. ellipsis: true,
  46. },
  47. ];
  48. const data = [
  49. {
  50. key: '1',
  51. name: 'John Brown',
  52. age: 32,
  53. address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
  54. tags: ['nice', 'developer'],
  55. },
  56. {
  57. key: '2',
  58. name: 'Jim Green',
  59. age: 42,
  60. address: 'London No. 2 Lake Park, London No. 2 Lake Park',
  61. tags: ['loser'],
  62. },
  63. {
  64. key: '3',
  65. name: 'Joe Black',
  66. age: 32,
  67. address: 'Sidney No. 1 Lake Park, Sidney No. 1 Lake Park',
  68. tags: ['cool', 'teacher'],
  69. },
  70. ];
  71. export default defineComponent({
  72. setup() {
  73. return {
  74. data,
  75. columns,
  76. };
  77. },
  78. });
  79. </script>

Table表格 - 图6

表格行/列合并

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

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

Table表格 - 图7

自定义筛选菜单

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

  1. <template>
  2. <a-table :data-source="data" :columns="columns">
  3. <template #filterDropdown="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }">
  4. <div style="padding: 8px">
  5. <a-input
  6. ref="searchInput"
  7. :placeholder="`Search ${column.dataIndex}`"
  8. :value="selectedKeys[0]"
  9. style="width: 188px; margin-bottom: 8px; display: block"
  10. @change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
  11. @pressEnter="handleSearch(selectedKeys, confirm, column.dataIndex)"
  12. />
  13. <a-button
  14. type="primary"
  15. size="small"
  16. style="width: 90px; margin-right: 8px"
  17. @click="handleSearch(selectedKeys, confirm, column.dataIndex)"
  18. >
  19. <template #icon><SearchOutlined /></template>
  20. Search
  21. </a-button>
  22. <a-button size="small" style="width: 90px" @click="handleReset(clearFilters)">
  23. Reset
  24. </a-button>
  25. </div>
  26. </template>
  27. <template #filterIcon="filtered">
  28. <search-outlined :style="{ color: filtered ? '#108ee9' : undefined }" />
  29. </template>
  30. <template #customRender="{ text, column }">
  31. <span v-if="searchText && searchedColumn === column.dataIndex">
  32. <template
  33. v-for="(fragment, i) in text
  34. .toString()
  35. .split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i'))"
  36. >
  37. <mark
  38. v-if="fragment.toLowerCase() === searchText.toLowerCase()"
  39. class="highlight"
  40. :key="i"
  41. >
  42. {{ fragment }}
  43. </mark>
  44. <template v-else>{{ fragment }}</template>
  45. </template>
  46. </span>
  47. <template v-else>
  48. {{ text }}
  49. </template>
  50. </template>
  51. </a-table>
  52. </template>
  53. <script>
  54. import { SearchOutlined } from '@ant-design/icons-vue';
  55. import { defineComponent, reactive, ref } from 'vue';
  56. const data = [
  57. {
  58. key: '1',
  59. name: 'John Brown',
  60. age: 32,
  61. address: 'New York No. 1 Lake Park',
  62. },
  63. {
  64. key: '2',
  65. name: 'Joe Black',
  66. age: 42,
  67. address: 'London No. 1 Lake Park',
  68. },
  69. {
  70. key: '3',
  71. name: 'Jim Green',
  72. age: 32,
  73. address: 'Sidney No. 1 Lake Park',
  74. },
  75. {
  76. key: '4',
  77. name: 'Jim Red',
  78. age: 32,
  79. address: 'London No. 2 Lake Park',
  80. },
  81. ];
  82. export default defineComponent({
  83. components: {
  84. SearchOutlined,
  85. },
  86. setup() {
  87. const state = reactive({
  88. searchText: '',
  89. searchedColumn: '',
  90. });
  91. const searchInput = ref();
  92. const columns = [
  93. {
  94. title: 'Name',
  95. dataIndex: 'name',
  96. key: 'name',
  97. slots: {
  98. filterDropdown: 'filterDropdown',
  99. filterIcon: 'filterIcon',
  100. customRender: 'customRender',
  101. },
  102. onFilter: (value, record) =>
  103. record.name.toString().toLowerCase().includes(value.toLowerCase()),
  104. onFilterDropdownVisibleChange: visible => {
  105. if (visible) {
  106. setTimeout(() => {
  107. console.log(searchInput.value);
  108. searchInput.value.focus();
  109. }, 0);
  110. }
  111. },
  112. },
  113. {
  114. title: 'Age',
  115. dataIndex: 'age',
  116. key: 'age',
  117. slots: {
  118. filterDropdown: 'filterDropdown',
  119. filterIcon: 'filterIcon',
  120. customRender: 'customRender',
  121. },
  122. onFilter: (value, record) =>
  123. record.age.toString().toLowerCase().includes(value.toLowerCase()),
  124. onFilterDropdownVisibleChange: visible => {
  125. if (visible) {
  126. setTimeout(() => {
  127. searchInput.value.focus();
  128. });
  129. }
  130. },
  131. },
  132. {
  133. title: 'Address',
  134. dataIndex: 'address',
  135. key: 'address',
  136. slots: {
  137. filterDropdown: 'filterDropdown',
  138. filterIcon: 'filterIcon',
  139. customRender: 'customRender',
  140. },
  141. onFilter: (value, record) =>
  142. record.address.toString().toLowerCase().includes(value.toLowerCase()),
  143. onFilterDropdownVisibleChange: visible => {
  144. if (visible) {
  145. setTimeout(() => {
  146. searchInput.value.focus();
  147. });
  148. }
  149. },
  150. },
  151. ];
  152. const handleSearch = (selectedKeys, confirm, dataIndex) => {
  153. confirm();
  154. console.log(selectedKeys[0]);
  155. state.searchText = selectedKeys[0];
  156. state.searchedColumn = dataIndex;
  157. };
  158. const handleReset = clearFilters => {
  159. clearFilters();
  160. state.searchText = '';
  161. };
  162. return {
  163. data,
  164. columns,
  165. handleSearch,
  166. handleReset,
  167. searchText: '',
  168. searchInput: null,
  169. searchedColumn: '',
  170. };
  171. },
  172. });
  173. </script>
  174. <style scoped>
  175. .highlight {
  176. background-color: rgb(255, 192, 105);
  177. padding: 0px;
  178. }
  179. </style>

Add

Table表格 - 图8

可编辑单元格

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

  1. <template>
  2. <a-button class="editable-add-btn" @click="handleAdd" style="margin-bottom: 8px">Add</a-button>
  3. <a-table bordered :data-source="dataSource" :columns="columns">
  4. <template #name="{ text, record }">
  5. <div class="editable-cell">
  6. <div v-if="editableData[record.key]" class="editable-cell-input-wrapper">
  7. <a-input v-model:value="editableData[record.key].name" @pressEnter="save(record.key)" />
  8. <check-outlined class="editable-cell-icon-check" @click="save(record.key)" />
  9. </div>
  10. <div v-else class="editable-cell-text-wrapper">
  11. {{ text || ' ' }}
  12. <edit-outlined class="editable-cell-icon" @click="edit(record.key)" />
  13. </div>
  14. </div>
  15. </template>
  16. <template #operation="{ record }">
  17. <a-popconfirm
  18. v-if="dataSource.length"
  19. title="Sure to delete?"
  20. @confirm="onDelete(record.key)"
  21. >
  22. <a>Delete</a>
  23. </a-popconfirm>
  24. </template>
  25. </a-table>
  26. </template>
  27. <script lang="ts">
  28. import { computed, defineComponent, reactive, Ref, ref, UnwrapRef } from 'vue';
  29. import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue';
  30. import { cloneDeep } from 'lodash-es';
  31. interface DataItem {
  32. key: string;
  33. name: string;
  34. age: number;
  35. address: string;
  36. }
  37. export default defineComponent({
  38. components: {
  39. CheckOutlined,
  40. EditOutlined,
  41. },
  42. setup() {
  43. const columns = [
  44. {
  45. title: 'name',
  46. dataIndex: 'name',
  47. width: '30%',
  48. slots: { customRender: 'name' },
  49. },
  50. {
  51. title: 'age',
  52. dataIndex: 'age',
  53. },
  54. {
  55. title: 'address',
  56. dataIndex: 'address',
  57. },
  58. {
  59. title: 'operation',
  60. dataIndex: 'operation',
  61. slots: { customRender: 'operation' },
  62. },
  63. ];
  64. const dataSource: Ref<DataItem[]> = ref([
  65. {
  66. key: '0',
  67. name: 'Edward King 0',
  68. age: 32,
  69. address: 'London, Park Lane no. 0',
  70. },
  71. {
  72. key: '1',
  73. name: 'Edward King 1',
  74. age: 32,
  75. address: 'London, Park Lane no. 1',
  76. },
  77. ]);
  78. const count = computed(() => dataSource.value.length + 1);
  79. const editableData: UnwrapRef<Record<string, DataItem>> = reactive({});
  80. const edit = (key: string) => {
  81. editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0]);
  82. };
  83. const save = (key: string) => {
  84. Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key]);
  85. delete editableData[key];
  86. };
  87. const onDelete = (key: string) => {
  88. dataSource.value = dataSource.value.filter(item => item.key !== key);
  89. };
  90. const handleAdd = () => {
  91. const newData = {
  92. key: `${count.value}`,
  93. name: `Edward King ${count.value}`,
  94. age: 32,
  95. address: `London, Park Lane no. ${count.value}`,
  96. };
  97. dataSource.value.push(newData);
  98. };
  99. return {
  100. columns,
  101. onDelete,
  102. handleAdd,
  103. dataSource,
  104. editableData,
  105. count,
  106. edit,
  107. save,
  108. };
  109. },
  110. });
  111. </script>
  112. <style lang="less">
  113. .editable-cell {
  114. position: relative;
  115. .editable-cell-input-wrapper,
  116. .editable-cell-text-wrapper {
  117. padding-right: 24px;
  118. }
  119. .editable-cell-text-wrapper {
  120. padding: 5px 24px 5px 5px;
  121. }
  122. .editable-cell-icon,
  123. .editable-cell-icon-check {
  124. position: absolute;
  125. right: 0;
  126. width: 20px;
  127. cursor: pointer;
  128. }
  129. .editable-cell-icon {
  130. margin-top: 4px;
  131. display: none;
  132. }
  133. .editable-cell-icon-check {
  134. line-height: 28px;
  135. }
  136. .editable-cell-icon:hover,
  137. .editable-cell-icon-check:hover {
  138. color: #108ee9;
  139. }
  140. .editable-add-btn {
  141. margin-bottom: 8px;
  142. }
  143. }
  144. .editable-cell:hover .editable-cell-icon {
  145. display: inline-block;
  146. }
  147. </style>

Table表格 - 图9

可编辑行

带行编辑功能的表格。

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

Table表格 - 图10

树形数据展示

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

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data" :row-selection="rowSelection" />
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent } from 'vue';
  6. const columns = [
  7. {
  8. title: 'Name',
  9. dataIndex: 'name',
  10. key: 'name',
  11. },
  12. {
  13. title: 'Age',
  14. dataIndex: 'age',
  15. key: 'age',
  16. width: '12%',
  17. },
  18. {
  19. title: 'Address',
  20. dataIndex: 'address',
  21. width: '30%',
  22. key: 'address',
  23. },
  24. ];
  25. interface DataItem {
  26. key: number;
  27. name: string;
  28. age: number;
  29. address: string;
  30. children?: DataItem[]
  31. }
  32. const data: DataItem[] = [
  33. {
  34. key: 1,
  35. name: 'John Brown sr.',
  36. age: 60,
  37. address: 'New York No. 1 Lake Park',
  38. children: [
  39. {
  40. key: 11,
  41. name: 'John Brown',
  42. age: 42,
  43. address: 'New York No. 2 Lake Park',
  44. },
  45. {
  46. key: 12,
  47. name: 'John Brown jr.',
  48. age: 30,
  49. address: 'New York No. 3 Lake Park',
  50. children: [
  51. {
  52. key: 121,
  53. name: 'Jimmy Brown',
  54. age: 16,
  55. address: 'New York No. 3 Lake Park',
  56. },
  57. ],
  58. },
  59. {
  60. key: 13,
  61. name: 'Jim Green sr.',
  62. age: 72,
  63. address: 'London No. 1 Lake Park',
  64. children: [
  65. {
  66. key: 131,
  67. name: 'Jim Green',
  68. age: 42,
  69. address: 'London No. 2 Lake Park',
  70. children: [
  71. {
  72. key: 1311,
  73. name: 'Jim Green jr.',
  74. age: 25,
  75. address: 'London No. 3 Lake Park',
  76. },
  77. {
  78. key: 1312,
  79. name: 'Jimmy Green sr.',
  80. age: 18,
  81. address: 'London No. 4 Lake Park',
  82. },
  83. ],
  84. },
  85. ],
  86. },
  87. ],
  88. },
  89. {
  90. key: 2,
  91. name: 'Joe Black',
  92. age: 32,
  93. address: 'Sidney No. 1 Lake Park',
  94. },
  95. ];
  96. const rowSelection = {
  97. onChange: (selectedRowKeys: (string | number)[], selectedRows: DataItem[]) => {
  98. console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  99. },
  100. onSelect: (record: DataItem, selected: boolean, selectedRows: DataItem[]) => {
  101. console.log(record, selected, selectedRows);
  102. },
  103. onSelectAll: (selected: boolean, selectedRows: DataItem[], changeRows: DataItem[]) => {
  104. console.log(selected, selectedRows, changeRows);
  105. },
  106. };
  107. export default defineComponent({
  108. setup() {
  109. return {
  110. data,
  111. columns,
  112. rowSelection,
  113. };
  114. },
  115. });
  116. </script>

Table表格 - 图11

可展开

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data">
  3. <template>
  4. <a>Delete</a>
  5. </template>
  6. <template #expandedRowRender="{ record }">
  7. <p style="margin: 0">
  8. {{ record.description }}
  9. </p>
  10. </template>
  11. </a-table>
  12. </template>
  13. <script lang="ts">
  14. import { defineComponent } from 'vue';
  15. const columns = [
  16. { title: 'Name', dataIndex: 'name', key: 'name' },
  17. { title: 'Age', dataIndex: 'age', key: 'age' },
  18. { title: 'Address', dataIndex: 'address', key: 'address' },
  19. { title: 'Action', dataIndex: '', key: 'x', slots: { customRender: 'action' } },
  20. ];
  21. const data = [
  22. {
  23. key: 1,
  24. name: 'John Brown',
  25. age: 32,
  26. address: 'New York No. 1 Lake Park',
  27. description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
  28. },
  29. {
  30. key: 2,
  31. name: 'Jim Green',
  32. age: 42,
  33. address: 'London No. 1 Lake Park',
  34. description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
  35. },
  36. {
  37. key: 3,
  38. name: 'Joe Black',
  39. age: 32,
  40. address: 'Sidney No. 1 Lake Park',
  41. description: 'My name is Joe Black, I am 32 years old, living in Sidney No. 1 Lake Park.',
  42. },
  43. ];
  44. export default defineComponent({
  45. setup() {
  46. return {
  47. data,
  48. columns,
  49. };
  50. },
  51. });
  52. </script>

Table表格 - 图12

固定头和列

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

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

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data" :scroll="{ x: 1500, y: 300 }">
  3. <template #action>
  4. <a>action</a>
  5. </template>
  6. </a-table>
  7. </template>
  8. <script lang="ts">
  9. import { defineComponent } from 'vue';
  10. const columns = [
  11. { title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
  12. { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
  13. { title: 'Column 1', dataIndex: 'address', key: '1', width: 150 },
  14. { title: 'Column 2', dataIndex: 'address', key: '2', width: 150 },
  15. { title: 'Column 3', dataIndex: 'address', key: '3', width: 150 },
  16. { title: 'Column 4', dataIndex: 'address', key: '4', width: 150 },
  17. { title: 'Column 5', dataIndex: 'address', key: '5', width: 150 },
  18. { title: 'Column 6', dataIndex: 'address', key: '6', width: 150 },
  19. { title: 'Column 7', dataIndex: 'address', key: '7', width: 150 },
  20. { title: 'Column 8', dataIndex: 'address', key: '8' },
  21. {
  22. title: 'Action',
  23. key: 'operation',
  24. fixed: 'right',
  25. width: 100,
  26. slots: { customRender: 'action' },
  27. },
  28. ];
  29. interface DataItem {
  30. key: number;
  31. name: string;
  32. age: number;
  33. address: string;
  34. }
  35. const data: DataItem[] = [];
  36. for (let i = 0; i < 100; i++) {
  37. data.push({
  38. key: i,
  39. name: `Edrward ${i}`,
  40. age: 32,
  41. address: `London Park no. ${i}`,
  42. });
  43. }
  44. export default defineComponent({
  45. data() {
  46. return {
  47. data,
  48. columns,
  49. };
  50. },
  51. });
  52. </script>

Table表格 - 图13

固定列

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

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

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data" :scroll="{ x: 1300 }">
  3. <template #action>
  4. <a>action</a>
  5. </template>
  6. </a-table>
  7. </template>
  8. <script lang="ts">
  9. import { defineComponent } from 'vue';
  10. const columns = [
  11. { title: 'Full Name', width: 100, dataIndex: 'name', key: 'name', fixed: 'left' },
  12. { title: 'Age', width: 100, dataIndex: 'age', key: 'age', fixed: 'left' },
  13. { title: 'Column 1', dataIndex: 'address', key: '1' },
  14. { title: 'Column 2', dataIndex: 'address', key: '2' },
  15. { title: 'Column 3', dataIndex: 'address', key: '3' },
  16. { title: 'Column 4', dataIndex: 'address', key: '4' },
  17. { title: 'Column 5', dataIndex: 'address', key: '5' },
  18. { title: 'Column 6', dataIndex: 'address', key: '6' },
  19. { title: 'Column 7', dataIndex: 'address', key: '7' },
  20. { title: 'Column 8', dataIndex: 'address', key: '8' },
  21. {
  22. title: 'Action',
  23. key: 'operation',
  24. fixed: 'right',
  25. width: 100,
  26. slots: { customRender: 'action' },
  27. },
  28. ];
  29. interface DataItem {
  30. key: string;
  31. name: string;
  32. age: number;
  33. address: string;
  34. }
  35. const data: DataItem[] = [
  36. {
  37. key: '1',
  38. name: 'John Brown',
  39. age: 32,
  40. address: 'New York Park',
  41. },
  42. {
  43. key: '2',
  44. name: 'Jim Green',
  45. age: 40,
  46. address: 'London Park',
  47. },
  48. ];
  49. export default defineComponent({
  50. data() {
  51. return {
  52. data,
  53. columns,
  54. };
  55. },
  56. });
  57. </script>

Table表格 - 图14

固定表头

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

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

  1. <template>
  2. <a-table
  3. :columns="columns"
  4. :data-source="data"
  5. :pagination="{ pageSize: 50 }"
  6. :scroll="{ y: 240 }"
  7. />
  8. </template>
  9. <script lang="ts">
  10. import { defineComponent } from 'vue';
  11. const columns = [
  12. {
  13. title: 'Name',
  14. dataIndex: 'name',
  15. width: 150,
  16. },
  17. {
  18. title: 'Age',
  19. dataIndex: 'age',
  20. width: 150,
  21. },
  22. {
  23. title: 'Address',
  24. dataIndex: 'address',
  25. },
  26. ];
  27. const data = [...Array(100)].map((_, i) => ({
  28. key: i,
  29. name: `Edward King ${i}`,
  30. age: 32,
  31. address: `London, Park Lane no. ${i}`,
  32. }));
  33. export default defineComponent({
  34. setup() {
  35. return {
  36. data,
  37. columns,
  38. };
  39. },
  40. });
  41. </script>

Table表格 - 图15

表头分组

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

  1. <template>
  2. <a-table
  3. :columns="columns"
  4. :data-source="data"
  5. bordered
  6. size="middle"
  7. :scroll="{ x: 'calc(700px + 50%)', y: 240 }"
  8. />
  9. </template>
  10. <script lang="ts">
  11. import { defineComponent } from 'vue';
  12. type TableDataType = {
  13. key: number;
  14. name: string;
  15. age: number;
  16. street: string;
  17. building: string;
  18. number: number;
  19. companyAddress: string;
  20. companyName: string;
  21. gender: string;
  22. };
  23. const columns = [
  24. {
  25. title: 'Name',
  26. dataIndex: 'name',
  27. key: 'name',
  28. width: 100,
  29. fixed: 'left',
  30. filters: [
  31. {
  32. text: 'Joe',
  33. value: 'Joe',
  34. },
  35. {
  36. text: 'John',
  37. value: 'John',
  38. },
  39. ],
  40. onFilter: (value: string, record: TableDataType) => record.name.indexOf(value) === 0,
  41. },
  42. {
  43. title: 'Other',
  44. children: [
  45. {
  46. title: 'Age',
  47. dataIndex: 'age',
  48. key: 'age',
  49. width: 200,
  50. sorter: (a: TableDataType, b: TableDataType) => a.age - b.age,
  51. },
  52. {
  53. title: 'Address',
  54. children: [
  55. {
  56. title: 'Street',
  57. dataIndex: 'street',
  58. key: 'street',
  59. width: 200,
  60. },
  61. {
  62. title: 'Block',
  63. children: [
  64. {
  65. title: 'Building',
  66. dataIndex: 'building',
  67. key: 'building',
  68. width: 100,
  69. },
  70. {
  71. title: 'Door No.',
  72. dataIndex: 'number',
  73. key: 'number',
  74. width: 100,
  75. },
  76. ],
  77. },
  78. ],
  79. },
  80. ],
  81. },
  82. {
  83. title: 'Company',
  84. children: [
  85. {
  86. title: 'Company Address',
  87. dataIndex: 'companyAddress',
  88. key: 'companyAddress',
  89. width: 200,
  90. },
  91. {
  92. title: 'Company Name',
  93. dataIndex: 'companyName',
  94. key: 'companyName',
  95. },
  96. ],
  97. },
  98. {
  99. title: 'Gender',
  100. dataIndex: 'gender',
  101. key: 'gender',
  102. width: 80,
  103. fixed: 'right',
  104. },
  105. ];
  106. const data = [...Array(100)].map((_, i) => ({
  107. key: i,
  108. name: 'John Brown',
  109. age: i + 1,
  110. street: 'Lake Park',
  111. building: 'C',
  112. number: 2035,
  113. companyAddress: 'Lake Street 42',
  114. companyName: 'SoftLake Co',
  115. gender: 'M',
  116. }));
  117. export default defineComponent({
  118. setup() {
  119. return {
  120. data,
  121. columns,
  122. };
  123. },
  124. });
  125. </script>

Table表格 - 图16

筛选和排序

对某一列数据进行筛选,使用列的 filters 属性来指定需要筛选菜单的列,onFilter 用于筛选当前数据,filterMultiple 用于指定多选和单选。 对某一列数据进行排序,通过指定列的 sorter 函数即可启动排序按钮。sorter: function(rowA, rowB) { ... }, rowA、rowB 为比较的两个行数据。 sortDirections: ['ascend' | 'descend']改变每列可用的排序方式,切换排序时按数组内容依次切换,设置在 table props 上时对所有列生效。 使用 defaultSortOrder 属性,设置列的默认排序顺序。

  1. <template>
  2. <a-table :columns="columns" :data-source="data" @change="onChange" />
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent } from 'vue';
  6. type TableDataType = {
  7. key: string;
  8. name: string;
  9. age: number;
  10. address: string;
  11. };
  12. type PaginationType = {
  13. current: number;
  14. pageSize: number;
  15. };
  16. type FilterType = {
  17. name: string;
  18. address: string;
  19. };
  20. type ColumnType = {
  21. title: string;
  22. dataIndex: string;
  23. filters?: {
  24. text: string;
  25. value: string;
  26. children?: {
  27. text: string;
  28. value: string;
  29. }[];
  30. }[];
  31. onFilter?: (value: string, record: TableDataType) => boolean;
  32. sorter?: (a: TableDataType, b: TableDataType) => number;
  33. sortDirections?: string[];
  34. defaultSortOrder?: string;
  35. filterMultiple?: string[] | boolean;
  36. };
  37. const columns: ColumnType[] = [
  38. {
  39. title: 'Name',
  40. dataIndex: 'name',
  41. filters: [
  42. {
  43. text: 'Joe',
  44. value: 'Joe',
  45. },
  46. {
  47. text: 'Jim',
  48. value: 'Jim',
  49. },
  50. {
  51. text: 'Submenu',
  52. value: 'Submenu',
  53. children: [
  54. {
  55. text: 'Green',
  56. value: 'Green',
  57. },
  58. {
  59. text: 'Black',
  60. value: 'Black',
  61. },
  62. ],
  63. },
  64. ],
  65. // specify the condition of filtering result
  66. // here is that finding the name started with `value`
  67. onFilter: (value: string, record: TableDataType) => record.name.indexOf(value) === 0,
  68. sorter: (a: TableDataType, b: TableDataType) => a.name.length - b.name.length,
  69. sortDirections: ['descend'],
  70. },
  71. {
  72. title: 'Age',
  73. dataIndex: 'age',
  74. defaultSortOrder: 'descend',
  75. sorter: (a: TableDataType, b: TableDataType) => a.age - b.age,
  76. },
  77. {
  78. title: 'Address',
  79. dataIndex: 'address',
  80. filters: [
  81. {
  82. text: 'London',
  83. value: 'London',
  84. },
  85. {
  86. text: 'New York',
  87. value: 'New York',
  88. },
  89. ],
  90. filterMultiple: false,
  91. onFilter: (value: string, record: TableDataType) => record.address.indexOf(value) === 0,
  92. sorter: (a: TableDataType, b: TableDataType) => a.address.length - b.address.length,
  93. sortDirections: ['descend', 'ascend'],
  94. },
  95. ];
  96. const data: TableDataType[] = [
  97. {
  98. key: '1',
  99. name: 'John Brown',
  100. age: 32,
  101. address: 'New York No. 1 Lake Park',
  102. },
  103. {
  104. key: '2',
  105. name: 'Jim Green',
  106. age: 42,
  107. address: 'London No. 1 Lake Park',
  108. },
  109. {
  110. key: '3',
  111. name: 'Joe Black',
  112. age: 32,
  113. address: 'Sidney No. 1 Lake Park',
  114. },
  115. {
  116. key: '4',
  117. name: 'Jim Red',
  118. age: 32,
  119. address: 'London No. 2 Lake Park',
  120. },
  121. ];
  122. export default defineComponent({
  123. setup() {
  124. const onChange = (pagination: PaginationType, filters: FilterType[], sorter: ColumnType) => {
  125. console.log('params', pagination, filters, sorter);
  126. };
  127. return {
  128. data,
  129. columns,
  130. onChange,
  131. };
  132. },
  133. });
  134. </script>

Table表格 - 图17

嵌套子表格

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

  1. <template>
  2. <a-table :columns="columns" :data-source="data" class="components-table-demo-nested">
  3. <template #operation>
  4. <a>Publish</a>
  5. </template>
  6. <template #expandedRowRender>
  7. <a-table :columns="innerColumns" :data-source="innerData" :pagination="false">
  8. <template #status>
  9. <span>
  10. <a-badge status="success" />
  11. Finished
  12. </span>
  13. </template>
  14. <template #operation>
  15. <span class="table-operation">
  16. <a>Pause</a>
  17. <a>Stop</a>
  18. <a-dropdown>
  19. <template #overlay>
  20. <a-menu>
  21. <a-menu-item>Action 1</a-menu-item>
  22. <a-menu-item>Action 2</a-menu-item>
  23. </a-menu>
  24. </template>
  25. <a>
  26. More
  27. <down-outlined />
  28. </a>
  29. </a-dropdown>
  30. </span>
  31. </template>
  32. </a-table>
  33. </template>
  34. </a-table>
  35. </template>
  36. <script lang="ts">
  37. import { DownOutlined } from '@ant-design/icons-vue';
  38. import { defineComponent } from 'vue';
  39. const columns = [
  40. { title: 'Name', dataIndex: 'name', key: 'name' },
  41. { title: 'Platform', dataIndex: 'platform', key: 'platform' },
  42. { title: 'Version', dataIndex: 'version', key: 'version' },
  43. { title: 'Upgraded', dataIndex: 'upgradeNum', key: 'upgradeNum' },
  44. { title: 'Creator', dataIndex: 'creator', key: 'creator' },
  45. { title: 'Date', dataIndex: 'createdAt', key: 'createdAt' },
  46. { title: 'Action', key: 'operation', slots: { customRender: 'operation' } },
  47. ];
  48. interface DataItem {
  49. key: number;
  50. name: string;
  51. platform: string;
  52. version: string;
  53. upgradeNum: number;
  54. creator: string;
  55. createdAt: string;
  56. }
  57. const data: DataItem[] = [];
  58. for (let i = 0; i < 3; ++i) {
  59. data.push({
  60. key: i,
  61. name: 'Screem',
  62. platform: 'iOS',
  63. version: '10.3.4.5654',
  64. upgradeNum: 500,
  65. creator: 'Jack',
  66. createdAt: '2014-12-24 23:12:00',
  67. });
  68. }
  69. const innerColumns = [
  70. { title: 'Date', dataIndex: 'date', key: 'date' },
  71. { title: 'Name', dataIndex: 'name', key: 'name' },
  72. { title: 'Status', key: 'state', slots: { customRender: 'status' } },
  73. { title: 'Upgrade Status', dataIndex: 'upgradeNum', key: 'upgradeNum' },
  74. {
  75. title: 'Action',
  76. dataIndex: 'operation',
  77. key: 'operation',
  78. slots: { customRender: 'operation' },
  79. },
  80. ];
  81. interface innerDataItem {
  82. key: number;
  83. date: string;
  84. name: string;
  85. upgradeNum: string;
  86. }
  87. const innerData: innerDataItem[] = [];
  88. for (let i = 0; i < 3; ++i) {
  89. innerData.push({
  90. key: i,
  91. date: '2014-12-24 23:12:00',
  92. name: 'This is production name',
  93. upgradeNum: 'Upgraded: 56',
  94. });
  95. }
  96. export default defineComponent({
  97. components: {
  98. DownOutlined,
  99. },
  100. setup() {
  101. return {
  102. data,
  103. columns,
  104. innerColumns,
  105. innerData,
  106. };
  107. },
  108. });
  109. </script>

Table表格 - 图18

可控的筛选和排序

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

  1. columns 中定义了 filteredValue 和 sortOrder 属性即视为受控模式。
  2. 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。
  3. 务必指定 column.key
  1. <template>
  2. <div>
  3. <div class="table-operations">
  4. <a-button @click="setAgeSort">Sort age</a-button>
  5. <a-button @click="clearFilters">Clear filters</a-button>
  6. <a-button @click="clearAll">Clear filters and sorters</a-button>
  7. </div>
  8. <a-table :columns="columns" :data-source="data" @change="handleChange" />
  9. </div>
  10. </template>
  11. <script lang="ts">
  12. import { computed, defineComponent, ref } from 'vue';
  13. import { TableState, TableStateFilters } from 'ant-design-vue/es/table/interface';
  14. type Pagination = TableState['pagination'];
  15. interface DataItem {
  16. key: string;
  17. name: string;
  18. age: number;
  19. address: string;
  20. }
  21. const data: DataItem[] = [
  22. {
  23. key: '1',
  24. name: 'John Brown',
  25. age: 32,
  26. address: 'New York No. 1 Lake Park',
  27. },
  28. {
  29. key: '2',
  30. name: 'Jim Green',
  31. age: 42,
  32. address: 'London No. 1 Lake Park',
  33. },
  34. {
  35. key: '3',
  36. name: 'Joe Black',
  37. age: 32,
  38. address: 'Sidney No. 1 Lake Park',
  39. },
  40. {
  41. key: '4',
  42. name: 'Jim Red',
  43. age: 32,
  44. address: 'London No. 2 Lake Park',
  45. },
  46. ];
  47. export default defineComponent({
  48. setup() {
  49. const filteredInfo = ref();
  50. const sortedInfo = ref();
  51. const columns = computed(() => {
  52. const filtered = filteredInfo.value || {};
  53. const sorted = sortedInfo.value || {};
  54. return [
  55. {
  56. title: 'Name',
  57. dataIndex: 'name',
  58. key: 'name',
  59. filters: [
  60. { text: 'Joe', value: 'Joe' },
  61. { text: 'Jim', value: 'Jim' },
  62. ],
  63. filteredValue: filtered.name || null,
  64. onFilter: (value: string, record: DataItem) => record.name.includes(value),
  65. sorter: (a: DataItem, b: DataItem) => a.name.length - b.name.length,
  66. sortOrder: sorted.columnKey === 'name' && sorted.order,
  67. ellipsis: true,
  68. },
  69. {
  70. title: 'Age',
  71. dataIndex: 'age',
  72. key: 'age',
  73. sorter: (a: DataItem, b: DataItem) => a.age - b.age,
  74. sortOrder: sorted.columnKey === 'age' && sorted.order,
  75. },
  76. {
  77. title: 'Address',
  78. dataIndex: 'address',
  79. key: 'address',
  80. filters: [
  81. { text: 'London', value: 'London' },
  82. { text: 'New York', value: 'New York' },
  83. ],
  84. filteredValue: filtered.address || null,
  85. onFilter: (value: string, record: DataItem) => record.address.includes(value),
  86. sorter: (a: DataItem, b: DataItem) => a.address.length - b.address.length,
  87. sortOrder: sorted.columnKey === 'address' && sorted.order,
  88. ellipsis: true,
  89. },
  90. ];
  91. });
  92. const handleChange = (pagination: Pagination, filters: TableStateFilters, sorter: any) => {
  93. console.log('Various parameters', pagination, filters, sorter);
  94. filteredInfo.value = filters;
  95. sortedInfo.value = sorter;
  96. };
  97. const clearFilters = () => {
  98. filteredInfo.value = null;
  99. };
  100. const clearAll = () => {
  101. filteredInfo.value = null;
  102. sortedInfo.value = null;
  103. };
  104. const setAgeSort = () => {
  105. sortedInfo.value = {
  106. order: 'descend',
  107. columnKey: 'age',
  108. };
  109. };
  110. return {
  111. data,
  112. columns,
  113. handleChange,
  114. clearFilters,
  115. clearAll,
  116. setAgeSort,
  117. };
  118. },
  119. });
  120. </script>
  121. <style scoped>
  122. .table-operations {
  123. margin-bottom: 16px;
  124. }
  125. .table-operations > button {
  126. margin-right: 8px;
  127. }
  128. </style>

Table表格 - 图19

选择和操作

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

  1. <template>
  2. <div>
  3. <div style="margin-bottom: 16px">
  4. <a-button type="primary" :disabled="!hasSelected" :loading="loading" @click="start">
  5. Reload
  6. </a-button>
  7. <span style="margin-left: 8px">
  8. <template v-if="hasSelected">
  9. {{ `Selected ${selectedRowKeys.length} items` }}
  10. </template>
  11. </span>
  12. </div>
  13. <a-table
  14. :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
  15. :columns="columns"
  16. :data-source="data"
  17. />
  18. </div>
  19. </template>
  20. <script lang="ts">
  21. import { computed, defineComponent, reactive, toRefs } from 'vue';
  22. import { ColumnProps } from 'ant-design-vue/es/table/interface';
  23. type Key = ColumnProps['key'];
  24. interface DataType {
  25. key: Key;
  26. name: string;
  27. age: number;
  28. address: string;
  29. }
  30. const columns = [
  31. {
  32. title: 'Name',
  33. dataIndex: 'name',
  34. },
  35. {
  36. title: 'Age',
  37. dataIndex: 'age',
  38. },
  39. {
  40. title: 'Address',
  41. dataIndex: 'address',
  42. },
  43. ];
  44. const data: DataType[] = [];
  45. for (let i = 0; i < 46; i++) {
  46. data.push({
  47. key: i,
  48. name: `Edward King ${i}`,
  49. age: 32,
  50. address: `London, Park Lane no. ${i}`,
  51. });
  52. }
  53. export default defineComponent({
  54. setup() {
  55. const state = reactive<{
  56. selectedRowKeys: Key[];
  57. loading: boolean;
  58. }>({
  59. selectedRowKeys: [], // Check here to configure the default column
  60. loading: false,
  61. });
  62. const hasSelected = computed(() => state.selectedRowKeys.length > 0);
  63. const start = () => {
  64. state.loading = true;
  65. // ajax request after empty completing
  66. setTimeout(() => {
  67. state.loading = false;
  68. state.selectedRowKeys = [];
  69. }, 1000);
  70. };
  71. const onSelectChange = (selectedRowKeys: Key[]) => {
  72. console.log('selectedRowKeys changed: ', selectedRowKeys);
  73. state.selectedRowKeys = selectedRowKeys;
  74. };
  75. return {
  76. data,
  77. columns,
  78. hasSelected,
  79. ...toRefs(state),
  80. // func
  81. start,
  82. onSelectChange,
  83. };
  84. },
  85. });
  86. </script>

Table表格 - 图20

自定义选择项

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

  1. <template>
  2. <a-table :row-selection="rowSelection" :columns="columns" :data-source="data" />
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent, computed, ref, unref } from 'vue';
  6. import { ColumnProps } from 'ant-design-vue/es/table/interface';
  7. type Key = ColumnProps['key'];
  8. interface DataType {
  9. key: Key;
  10. name: string;
  11. age: number;
  12. address: string;
  13. }
  14. const columns = [
  15. {
  16. title: 'Name',
  17. dataIndex: 'name',
  18. },
  19. {
  20. title: 'Age',
  21. dataIndex: 'age',
  22. },
  23. {
  24. title: 'Address',
  25. dataIndex: 'address',
  26. },
  27. ];
  28. const data: DataType[] = [];
  29. for (let i = 0; i < 46; i++) {
  30. data.push({
  31. key: i,
  32. name: `Edward King ${i}`,
  33. age: 32,
  34. address: `London, Park Lane no. ${i}`,
  35. });
  36. }
  37. export default defineComponent({
  38. setup() {
  39. const selectedRowKeys = ref<Key[]>([]); // Check here to configure the default column
  40. const onSelectChange = (changableRowKeys: Key[]) => {
  41. console.log('selectedRowKeys changed: ', changableRowKeys);
  42. selectedRowKeys.value = changableRowKeys;
  43. };
  44. const rowSelection = computed(() => {
  45. return {
  46. selectedRowKeys: unref(selectedRowKeys),
  47. onChange: onSelectChange,
  48. hideDefaultSelections: true,
  49. selections: [
  50. {
  51. key: 'all-data',
  52. text: 'Select All Data',
  53. onSelect: () => {
  54. selectedRowKeys.value = [...Array(46).keys()]; // 0...45
  55. },
  56. },
  57. {
  58. key: 'odd',
  59. text: 'Select Odd Row',
  60. onSelect: (changableRowKeys: Key[]) => {
  61. let newSelectedRowKeys = [];
  62. newSelectedRowKeys = changableRowKeys.filter((key, index) => {
  63. if (index % 2 !== 0) {
  64. return false;
  65. }
  66. return true;
  67. });
  68. selectedRowKeys.value = newSelectedRowKeys;
  69. },
  70. },
  71. {
  72. key: 'even',
  73. text: 'Select Even Row',
  74. onSelect: (changableRowKeys: Key[]) => {
  75. let newSelectedRowKeys = [];
  76. newSelectedRowKeys = changableRowKeys.filter((key, index) => {
  77. if (index % 2 !== 0) {
  78. return true;
  79. }
  80. return false;
  81. });
  82. selectedRowKeys.value = newSelectedRowKeys;
  83. },
  84. },
  85. ],
  86. };
  87. });
  88. return {
  89. data,
  90. columns,
  91. selectedRowKeys,
  92. rowSelection,
  93. };
  94. },
  95. });
  96. </script>

Table表格 - 图21

可选择

第一列是联动的选择框。
默认点击 checkbox 触发选择行为,需要 点击行 触发可参考例子:https://codesandbox.io/s/row-selection-on-click-tr58v

  1. <template>
  2. <a-table :row-selection="rowSelection" :columns="columns" :data-source="data">
  3. <template #name="{ text }">
  4. <a>{{ text }}</a>
  5. </template>
  6. </a-table>
  7. </template>
  8. <script lang="ts">
  9. import { defineComponent } from 'vue';
  10. import { ColumnProps } from 'ant-design-vue/es/table/interface';
  11. type Key = ColumnProps['key'];
  12. interface DataType {
  13. key: Key;
  14. name: string;
  15. age: number;
  16. address: string;
  17. }
  18. const columns = [
  19. {
  20. title: 'Name',
  21. dataIndex: 'name',
  22. slots: { customRender: 'name' },
  23. },
  24. {
  25. title: 'Age',
  26. dataIndex: 'age',
  27. },
  28. {
  29. title: 'Address',
  30. dataIndex: 'address',
  31. },
  32. ];
  33. const data: DataType[] = [
  34. {
  35. key: '1',
  36. name: 'John Brown',
  37. age: 32,
  38. address: 'New York No. 1 Lake Park',
  39. },
  40. {
  41. key: '2',
  42. name: 'Jim Green',
  43. age: 42,
  44. address: 'London No. 1 Lake Park',
  45. },
  46. {
  47. key: '3',
  48. name: 'Joe Black',
  49. age: 32,
  50. address: 'Sidney No. 1 Lake Park',
  51. },
  52. {
  53. key: '4',
  54. name: 'Disabled User',
  55. age: 99,
  56. address: 'Sidney No. 1 Lake Park',
  57. },
  58. ];
  59. export default defineComponent({
  60. setup() {
  61. const rowSelection = {
  62. onChange: (selectedRowKeys: Key[], selectedRows: DataType[]) => {
  63. console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
  64. },
  65. getCheckboxProps: (record: DataType) => ({
  66. disabled: record.name === 'Disabled User', // Column configuration not to be checked
  67. name: record.name,
  68. }),
  69. };
  70. return {
  71. data,
  72. columns,
  73. rowSelection,
  74. };
  75. },
  76. });
  77. </script>

Table表格 - 图22

紧凑型

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

  1. <template>
  2. <div id="components-table-demo-size">
  3. <h4>Middle size table</h4>
  4. <a-table :columns="columns" :data-source="data" size="middle" />
  5. <h4>Small size table</h4>
  6. <a-table :columns="columns" :data-source="data" size="small" />
  7. </div>
  8. </template>
  9. <script lang="ts">
  10. import { defineComponent } from 'vue';
  11. const columns = [
  12. { title: 'Name', dataIndex: 'name' },
  13. { title: 'Age', dataIndex: 'age' },
  14. { title: 'Address', dataIndex: 'address' },
  15. ];
  16. const data = [
  17. {
  18. key: '1',
  19. name: 'John Brown',
  20. age: 32,
  21. address: 'New York No. 1 Lake Park',
  22. },
  23. {
  24. key: '2',
  25. name: 'Jim Green',
  26. age: 42,
  27. address: 'London No. 1 Lake Park',
  28. },
  29. {
  30. key: '3',
  31. name: 'Joe Black',
  32. age: 32,
  33. address: 'Sidney No. 1 Lake Park',
  34. },
  35. ];
  36. export default defineComponent({
  37. setup() {
  38. return {
  39. data,
  40. columns,
  41. };
  42. },
  43. });
  44. </script>
  45. <style>
  46. #components-table-demo-size h4 {
  47. margin-bottom: 16px;
  48. }
  49. </style>

Table表格 - 图23

Table表格 - 图24

带斑马纹表格

利用 rowClassName 自定义带斑马纹的表格。

  1. <template>
  2. <a-table
  3. class="ant-table-striped"
  4. size="middle"
  5. :columns="columns"
  6. :data-source="data"
  7. :rowClassName="(record, index) => (index % 2 === 1 ? 'table-striped' : null)"
  8. />
  9. <a-table
  10. class="ant-table-striped"
  11. size="middle"
  12. :columns="columns"
  13. :data-source="data"
  14. :rowClassName="(record, index) => (index % 2 === 1 ? 'table-striped' : null)"
  15. bordered
  16. />
  17. </template>
  18. <script lang="ts">
  19. import { defineComponent } from 'vue';
  20. const columns = [
  21. { title: 'Name', dataIndex: 'name' },
  22. { title: 'Age', dataIndex: 'age' },
  23. { title: 'Address', dataIndex: 'address' },
  24. ];
  25. const data = [
  26. {
  27. key: '1',
  28. name: 'John Brown',
  29. age: 32,
  30. address: 'New York No. 1 Lake Park',
  31. },
  32. {
  33. key: '2',
  34. name: 'Jim Green',
  35. age: 42,
  36. address: 'London No. 1 Lake Park',
  37. },
  38. {
  39. key: '3',
  40. name: 'Joe Black',
  41. age: 32,
  42. address: 'Sidney No. 1 Lake Park',
  43. },
  44. {
  45. key: '4',
  46. name: 'Ben Kang',
  47. age: 15,
  48. address: 'Sidney No. 1 Lake Park',
  49. },
  50. ];
  51. export default defineComponent({
  52. setup() {
  53. return {
  54. data,
  55. columns,
  56. };
  57. },
  58. });
  59. </script>
  60. <style scoped>
  61. .ant-table-striped :deep(.table-striped) {
  62. background-color: #fafafa;
  63. }
  64. </style>

Table表格 - 图25

template 风格的 API

使用 template 风格的 API

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

  1. <template>
  2. <a-table :data-source="data">
  3. <a-table-column-group>
  4. <template #title><span style="color: #1890ff">Name</span></template>
  5. <a-table-column key="firstName" data-index="firstName">
  6. <template #title><span style="color: #1890ff">First Name</span></template>
  7. </a-table-column>
  8. <a-table-column key="lastName" title="Last Name" data-index="lastName" />
  9. </a-table-column-group>
  10. <a-table-column key="age" title="Age" data-index="age" />
  11. <a-table-column key="address" title="Address" data-index="address" />
  12. <a-table-column key="tags" title="Tags" data-index="tags">
  13. <template #default="{ text: tags }">
  14. <span>
  15. <a-tag v-for="tag in tags" :key="tag" color="blue">{{ tag }}</a-tag>
  16. </span>
  17. </template>
  18. </a-table-column>
  19. <a-table-column key="action" title="Action">
  20. <template #default="{ record }">
  21. <span>
  22. <a>Action 一 {{ record.firstName }}</a>
  23. <a-divider type="vertical" />
  24. <a>Delete</a>
  25. </span>
  26. </template>
  27. </a-table-column>
  28. </a-table>
  29. </template>
  30. <script lang="ts">
  31. import { defineComponent } from 'vue';
  32. const data = [
  33. {
  34. key: '1',
  35. firstName: 'John',
  36. lastName: 'Brown',
  37. age: 32,
  38. address: 'New York No. 1 Lake Park',
  39. tags: ['nice', 'developer'],
  40. },
  41. {
  42. key: '2',
  43. firstName: 'Jim',
  44. lastName: 'Green',
  45. age: 42,
  46. address: 'London No. 1 Lake Park',
  47. tags: ['loser'],
  48. },
  49. {
  50. key: '3',
  51. firstName: 'Joe',
  52. lastName: 'Black',
  53. age: 32,
  54. address: 'Sidney No. 1 Lake Park',
  55. tags: ['cool', 'teacher'],
  56. },
  57. ];
  58. export default defineComponent({
  59. setup() {
  60. return {
  61. data,
  62. };
  63. },
  64. });
  65. </script>

API

Table

参数说明类型默认值版本
tableLayout表格元素的 table-layout 属性,设为 fixed 表示内容不会影响列的布局- | ‘auto’ | ‘fixed’
固定表头/列或使用了 column.ellipsis 时,默认值为 fixed
1.5.0
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 | #expandedRowRender=”{record, index, indent, expanded}”-
expandIcon自定义展开图标Function(props):VNode | #expandIcon=”props”-
expandRowByClick通过点击行来展开子行booleanfalse
expandIconColumnIndex展开的图标显示在哪一列,如果没有 rowSelection,默认显示在第一列,否则显示在选择框后面number
footer表格尾部Function(currentPageData)|v-slot
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 | middle | smalldefault
title表格标题Function(currentPageData)|v-slot
customHeaderRow设置头部行属性Function(column, index)-
customRow设置行属性Function(record, index)-
getPopupContainer设置表格内各类浮层的渲染节点,如筛选菜单(triggerNode) => HTMLElement() => TableHtmlElement1.5.0
transformCellText数据渲染前可以再次改变,一般用户空数据的默认配置,可以通过 ConfigProvider 全局统一配置Function({ text, column, record, index }) => any-1.5.4

事件

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

customRow 用法

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

  1. <Table
  2. customRow={(record) => {
  3. return {
  4. xxx... //属性
  5. onClick: (event) => {}, // 点击行
  6. onDblclick: (event) => {},
  7. onContextmenu: (event) => {},
  8. onMouseenter: (event) => {}, // 鼠标移入行
  9. onMouseleave: (event) => {}
  10. };
  11. }}
  12. customHeaderRow={(column) => {
  13. return {
  14. onClick: () => {}, // 点击表头行
  15. };
  16. }}
  17. />

Column

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

参数说明类型默认值版本
align设置列内容的对齐方式‘left’ | ‘right’ | ‘center’‘left’
ellipsis超过宽度将自动省略,暂不支持和排序筛选一起使用。
设置为 true 时,表格布局将变成 tableLayout=”fixed”
booleanfalse1.5.0
colSpan表头列合并,设置为 0 时,不渲染number
dataIndex列数据在数据项中对应的 key,支持 a.b.c 的嵌套写法string-
defaultFilteredValue默认筛选值string[]-1.5.0
filterDropdown可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互VNode | v-slot-
filterDropdownVisible用于控制自定义筛选菜单是否可见boolean-
filtered标识数据是否经过过滤,筛选图标会高亮booleanfalse
filteredValue筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组string[]-
filterIcon自定义 filter 图标。VNode | ({filtered: boolean, column: Column}) => vNode |slotfalse
filterMultiple是否多选booleantrue
filters表头的筛选菜单项object[]-
fixed列是否固定,可选 true(等效于 left) ‘left’ ‘right’boolean|stringfalse
keyVue 需要的 key,如果已经设置了唯一的 dataIndex,可以忽略这个属性string-
customRender生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并,可参考 demo 表格行/列合并Function({text, record, index}) {}|v-slot-
sorter排序函数,本地排序使用一个函数(参考 Array.sort 的 compareFunction),需要服务端排序可设为 trueFunction|boolean-
sortOrder排序的受控属性,外界可用此控制列的排序,可设置为 ‘ascend’ ‘descend’ falseboolean|string-
sortDirections支持的排序方式,取值为 ‘ascend’ ‘descend’Array[‘ascend’, ‘descend’]1.5.0
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-

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)-

scroll

参数说明类型默认值版本
x设置横向滚动,也可用于指定滚动区域的宽和高,可以设置为像素值,百分比,true 和 ‘max-content’number | true-
y设置纵向滚动,也可用于指定滚动区域的宽和高,可以设置为像素值,百分比,true 和 ‘max-content’number | true-
scrollToFirstRowOnChange当分页、排序、筛选变化后是否滚动到表格顶部boolean-1.5.0

selection

自定义选择配置项

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

注意

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

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

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