Table 表格
展示行列数据。
何时使用
- 当有大量结构化的数据需要展现时;
- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。
如何使用
指定表格的数据源 dataSource
为一个数组。
代码演示
基本用法
简单的表格,最后一列是各种操作。
<template>
<a-table :columns="columns" :data-source="data">
<a slot="name" slot-scope="text">{{ text }}</a>
<span slot="customTitle"><a-icon type="smile-o" /> Name</span>
<span slot="tags" slot-scope="tags">
<a-tag
v-for="tag in tags"
:key="tag"
:color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
>
{{ tag.toUpperCase() }}
</a-tag>
</span>
<span slot="action" slot-scope="text, record">
<a>Invite 一 {{ record.name }}</a>
<a-divider type="vertical" />
<a>Delete</a>
<a-divider type="vertical" />
<a class="ant-dropdown-link"> More actions <a-icon type="down" /> </a>
</span>
</a-table>
</template>
<script>
const columns = [
{
dataIndex: 'name',
key: 'name',
slots: { title: 'customTitle' },
scopedSlots: { customRender: 'name' },
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
{
title: 'Tags',
key: 'tags',
dataIndex: 'tags',
scopedSlots: { customRender: 'tags' },
},
{
title: 'Action',
key: 'action',
scopedSlots: { customRender: 'action' },
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
export default {
data() {
return {
data,
columns,
};
},
};
</script>
单元格自动省略
设置 column.ellipsis
可以让单元格内容根据宽度自动省略。
列头缩略暂不支持和排序筛选一起使用。
<template>
<a-table :columns="columns" :data-source="data">
<a slot="name" slot-scope="text">{{ text }}</a>
</a-table>
</template>
<script>
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
scopedSlots: { customRender: 'name' },
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
width: 80,
},
{
title: 'Address',
dataIndex: 'address',
key: 'address 1',
ellipsis: true,
},
{
title: 'Long Column Long Column Long Column',
dataIndex: 'address',
key: 'address 2',
ellipsis: true,
},
{
title: 'Long Column Long Column',
dataIndex: 'address',
key: 'address 3',
ellipsis: true,
},
{
title: 'Long Column',
dataIndex: 'address',
key: 'address 4',
ellipsis: true,
},
];
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park, New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 2 Lake Park, London No. 2 Lake Park',
tags: ['loser'],
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park, Sidney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
export default {
data() {
return {
data,
columns,
};
},
};
</script>
远程加载数据
这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。
另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 onFilter
和 sorter
函数,而是在把筛选和排序的参数发到服务端来处理。
注意,此示例使用 模拟接口,展示数据可能不准确,请打开网络面板查看请求。
<template>
<a-table
:columns="columns"
:row-key="record => record.login.uuid"
:data-source="data"
:pagination="pagination"
:loading="loading"
@change="handleTableChange"
>
<template slot="name" slot-scope="name"> {{ name.first }} {{ name.last }} </template>
</a-table>
</template>
<script>
import reqwest from 'reqwest';
const columns = [
{
title: 'Name',
dataIndex: 'name',
sorter: true,
width: '20%',
scopedSlots: { customRender: 'name' },
},
{
title: 'Gender',
dataIndex: 'gender',
filters: [
{ text: 'Male', value: 'male' },
{ text: 'Female', value: 'female' },
],
width: '20%',
},
{
title: 'Email',
dataIndex: 'email',
},
];
export default {
data() {
return {
data: [],
pagination: {},
loading: false,
columns,
};
},
mounted() {
this.fetch();
},
methods: {
handleTableChange(pagination, filters, sorter) {
console.log(pagination);
const pager = { ...this.pagination };
pager.current = pagination.current;
this.pagination = pager;
this.fetch({
results: pagination.pageSize,
page: pagination.current,
sortField: sorter.field,
sortOrder: sorter.order,
...filters,
});
},
fetch(params = {}) {
console.log('params:', params);
this.loading = true;
reqwest({
url: 'https://randomuser.me/api',
method: 'get',
data: {
results: 10,
...params,
},
type: 'json',
}).then(data => {
const pagination = { ...this.pagination };
// Read total count from server
// pagination.total = data.totalCount;
pagination.total = 200;
this.loading = false;
this.data = data.results;
this.pagination = pagination;
});
},
},
};
</script>
带边框
添加表格边框线,页头和页脚。
<template>
<a-table :columns="columns" :data-source="data" bordered>
<template slot="name" slot-scope="text">
<a>{{ text }}</a>
</template>
<template slot="title" slot-scope="currentPageData">
Header
</template>
<template slot="footer" slot-scope="currentPageData">
Footer
</template>
</a-table>
</template>
<script>
const columns = [
{
title: 'Name',
dataIndex: 'name',
scopedSlots: { customRender: 'name' },
},
{
title: 'Cash Assets',
className: 'column-money',
dataIndex: 'money',
},
{
title: 'Address',
dataIndex: 'address',
},
];
const data = [
{
key: '1',
name: 'John Brown',
money: '¥300,000.00',
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
money: '¥1,256,000.00',
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
money: '¥120,000.00',
address: 'Sidney No. 1 Lake Park',
},
];
export default {
data() {
return {
data,
columns,
};
},
};
</script>
<style>
th.column-money,
td.column-money {
text-align: right !important;
}
</style>
表格行/列合并
表头只支持列合并,使用 column 里的 colSpan 进行设置。
表格支持行/列合并,使用 render 里的单元格属性 colSpan 或者 rowSpan 设值为 0 时,设置的表格不会渲染。
<template>
<a-table :columns="columns" :data-source="data" bordered>
<template slot="name" slot-scope="text">
<a>{{ text }}</a>
</template>
</a-table>
</template>
<script>
// In the fifth row, other columns are merged into first column
// by setting it's colSpan to be 0
const renderContent = (value, row, index) => {
const obj = {
children: value,
attrs: {},
};
if (index === 4) {
obj.attrs.colSpan = 0;
}
return obj;
};
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
tel: '0571-22098909',
phone: 18889898989,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
tel: '0571-22098333',
phone: 18889898888,
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
age: 32,
tel: '0575-22098909',
phone: 18900010002,
address: 'Sidney No. 1 Lake Park',
},
{
key: '4',
name: 'Jim Red',
age: 18,
tel: '0575-22098909',
phone: 18900010002,
address: 'London No. 2 Lake Park',
},
{
key: '5',
name: 'Jake White',
age: 18,
tel: '0575-22098909',
phone: 18900010002,
address: 'Dublin No. 2 Lake Park',
},
];
export default {
data() {
const columns = [
{
title: 'Name',
dataIndex: 'name',
customRender: (text, row, index) => {
if (index < 4) {
return <a href="javascript:;">{text}</a>;
}
return {
children: <a href="javascript:;">{text}</a>,
attrs: {
colSpan: 5,
},
};
},
},
{
title: 'Age',
dataIndex: 'age',
customRender: renderContent,
},
{
title: 'Home phone',
colSpan: 2,
dataIndex: 'tel',
customRender: (value, row, index) => {
const obj = {
children: value,
attrs: {},
};
if (index === 2) {
obj.attrs.rowSpan = 2;
}
// These two are merged into above cell
if (index === 3) {
obj.attrs.rowSpan = 0;
}
if (index === 4) {
obj.attrs.colSpan = 0;
}
return obj;
},
},
{
title: 'Phone',
colSpan: 0,
dataIndex: 'phone',
customRender: renderContent,
},
{
title: 'Address',
dataIndex: 'address',
customRender: renderContent,
},
];
return {
data,
columns,
};
},
};
</script>
自定义筛选菜单
通过 filterDropdown
定义自定义的列筛选功能,并实现一个搜索列的示例。
<template>
<a-table :data-source="data" :columns="columns">
<div
slot="filterDropdown"
slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }"
style="padding: 8px"
>
<a-input
v-ant-ref="c => (searchInput = c)"
:placeholder="`Search ${column.dataIndex}`"
:value="selectedKeys[0]"
style="width: 188px; margin-bottom: 8px; display: block;"
@change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
@pressEnter="() => handleSearch(selectedKeys, confirm, column.dataIndex)"
/>
<a-button
type="primary"
icon="search"
size="small"
style="width: 90px; margin-right: 8px"
@click="() => handleSearch(selectedKeys, confirm, column.dataIndex)"
>
Search
</a-button>
<a-button size="small" style="width: 90px" @click="() => handleReset(clearFilters)">
Reset
</a-button>
</div>
<a-icon
slot="filterIcon"
slot-scope="filtered"
type="search"
:style="{ color: filtered ? '#108ee9' : undefined }"
/>
<template slot="customRender" slot-scope="text, record, index, column">
<span v-if="searchText && searchedColumn === column.dataIndex">
<template
v-for="(fragment, i) in text
.toString()
.split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i'))"
>
<mark
v-if="fragment.toLowerCase() === searchText.toLowerCase()"
:key="i"
class="highlight"
>{{ fragment }}</mark
>
<template v-else>{{ fragment }}</template>
</template>
</span>
<template v-else>
{{ text }}
</template>
</template>
</a-table>
</template>
<script>
const data = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Joe Black',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Jim Green',
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,
searchText: '',
searchInput: null,
searchedColumn: '',
columns: [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
scopedSlots: {
filterDropdown: 'filterDropdown',
filterIcon: 'filterIcon',
customRender: 'customRender',
},
onFilter: (value, record) =>
record.name
.toString()
.toLowerCase()
.includes(value.toLowerCase()),
onFilterDropdownVisibleChange: visible => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
}, 0);
}
},
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
scopedSlots: {
filterDropdown: 'filterDropdown',
filterIcon: 'filterIcon',
customRender: 'customRender',
},
onFilter: (value, record) =>
record.age
.toString()
.toLowerCase()
.includes(value.toLowerCase()),
onFilterDropdownVisibleChange: visible => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
});
}
},
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
scopedSlots: {
filterDropdown: 'filterDropdown',
filterIcon: 'filterIcon',
customRender: 'customRender',
},
onFilter: (value, record) =>
record.address
.toString()
.toLowerCase()
.includes(value.toLowerCase()),
onFilterDropdownVisibleChange: visible => {
if (visible) {
setTimeout(() => {
this.searchInput.focus();
});
}
},
},
],
};
},
methods: {
handleSearch(selectedKeys, confirm, dataIndex) {
confirm();
this.searchText = selectedKeys[0];
this.searchedColumn = dataIndex;
},
handleReset(clearFilters) {
clearFilters();
this.searchText = '';
},
},
};
</script>
<style scoped>
.highlight {
background-color: rgb(255, 192, 105);
padding: 0px;
}
</style>
可编辑单元格
带单元格编辑功能的表格。
<template>
<div>
<a-button class="editable-add-btn" @click="handleAdd">
Add
</a-button>
<a-table bordered :data-source="dataSource" :columns="columns">
<template slot="name" slot-scope="text, record">
<editable-cell :text="text" @change="onCellChange(record.key, 'name', $event)" />
</template>
<template slot="operation" slot-scope="text, record">
<a-popconfirm
v-if="dataSource.length"
title="Sure to delete?"
@confirm="() => onDelete(record.key)"
>
<a href="javascript:;">Delete</a>
</a-popconfirm>
</template>
</a-table>
</div>
</template>
<script>
const EditableCell = {
template: `
<div class="editable-cell">
<div v-if="editable" class="editable-cell-input-wrapper">
<a-input :value="value" @change="handleChange" @pressEnter="check" /><a-icon
type="check"
class="editable-cell-icon-check"
@click="check"
/>
</div>
<div v-else class="editable-cell-text-wrapper">
{{ value || ' ' }}
<a-icon type="edit" class="editable-cell-icon" @click="edit" />
</div>
</div>
`,
props: {
text: String,
},
data() {
return {
value: this.text,
editable: false,
};
},
methods: {
handleChange(e) {
const value = e.target.value;
this.value = value;
},
check() {
this.editable = false;
this.$emit('change', this.value);
},
edit() {
this.editable = true;
},
},
};
export default {
components: {
EditableCell,
},
data() {
return {
dataSource: [
{
key: '0',
name: 'Edward King 0',
age: '32',
address: 'London, Park Lane no. 0',
},
{
key: '1',
name: 'Edward King 1',
age: '32',
address: 'London, Park Lane no. 1',
},
],
count: 2,
columns: [
{
title: 'name',
dataIndex: 'name',
width: '30%',
scopedSlots: { customRender: 'name' },
},
{
title: 'age',
dataIndex: 'age',
},
{
title: 'address',
dataIndex: 'address',
},
{
title: 'operation',
dataIndex: 'operation',
scopedSlots: { customRender: 'operation' },
},
],
};
},
methods: {
onCellChange(key, dataIndex, value) {
const dataSource = [...this.dataSource];
const target = dataSource.find(item => item.key === key);
if (target) {
target[dataIndex] = value;
this.dataSource = dataSource;
}
},
onDelete(key) {
const dataSource = [...this.dataSource];
this.dataSource = dataSource.filter(item => item.key !== key);
},
handleAdd() {
const { count, dataSource } = this;
const newData = {
key: count,
name: `Edward King ${count}`,
age: 32,
address: `London, Park Lane no. ${count}`,
};
this.dataSource = [...dataSource, newData];
this.count = count + 1;
},
},
};
</script>
<style>
.editable-cell {
position: relative;
}
.editable-cell-input-wrapper,
.editable-cell-text-wrapper {
padding-right: 24px;
}
.editable-cell-text-wrapper {
padding: 5px 24px 5px 5px;
}
.editable-cell-icon,
.editable-cell-icon-check {
position: absolute;
right: 0;
width: 20px;
cursor: pointer;
}
.editable-cell-icon {
line-height: 18px;
display: none;
}
.editable-cell-icon-check {
line-height: 28px;
}
.editable-cell:hover .editable-cell-icon {
display: inline-block;
}
.editable-cell-icon:hover,
.editable-cell-icon-check:hover {
color: #108ee9;
}
.editable-add-btn {
margin-bottom: 8px;
}
</style>
可编辑行
带行编辑功能的表格。
<template>
<a-table :columns="columns" :data-source="data" bordered>
<template
v-for="col in ['name', 'age', 'address']"
:slot="col"
slot-scope="text, record, index"
>
<div :key="col">
<a-input
v-if="record.editable"
style="margin: -5px 0"
:value="text"
@change="e => handleChange(e.target.value, record.key, col)"
/>
<template v-else>
{{ text }}
</template>
</div>
</template>
<template slot="operation" slot-scope="text, record, index">
<div class="editable-row-operations">
<span v-if="record.editable">
<a @click="() => save(record.key)">Save</a>
<a-popconfirm title="Sure to cancel?" @confirm="() => cancel(record.key)">
<a>Cancel</a>
</a-popconfirm>
</span>
<span v-else>
<a :disabled="editingKey !== ''" @click="() => edit(record.key)">Edit</a>
</span>
</div>
</template>
</a-table>
</template>
<script>
const columns = [
{
title: 'name',
dataIndex: 'name',
width: '25%',
scopedSlots: { customRender: 'name' },
},
{
title: 'age',
dataIndex: 'age',
width: '15%',
scopedSlots: { customRender: 'age' },
},
{
title: 'address',
dataIndex: 'address',
width: '40%',
scopedSlots: { customRender: 'address' },
},
{
title: 'operation',
dataIndex: 'operation',
scopedSlots: { customRender: 'operation' },
},
];
const data = [];
for (let i = 0; i < 100; i++) {
data.push({
key: i.toString(),
name: `Edrward ${i}`,
age: 32,
address: `London Park no. ${i}`,
});
}
export default {
data() {
this.cacheData = data.map(item => ({ ...item }));
return {
data,
columns,
editingKey: '',
};
},
methods: {
handleChange(value, key, column) {
const newData = [...this.data];
const target = newData.filter(item => key === item.key)[0];
if (target) {
target[column] = value;
this.data = newData;
}
},
edit(key) {
const newData = [...this.data];
const target = newData.filter(item => key === item.key)[0];
this.editingKey = key;
if (target) {
target.editable = true;
this.data = newData;
}
},
save(key) {
const newData = [...this.data];
const newCacheData = [...this.cacheData];
const target = newData.filter(item => key === item.key)[0];
const targetCache = newCacheData.filter(item => key === item.key)[0];
if (target && targetCache) {
delete target.editable;
this.data = newData;
Object.assign(targetCache, target);
this.cacheData = newCacheData;
}
this.editingKey = '';
},
cancel(key) {
const newData = [...this.data];
const target = newData.filter(item => key === item.key)[0];
this.editingKey = '';
if (target) {
Object.assign(target, this.cacheData.filter(item => key === item.key)[0]);
delete target.editable;
this.data = newData;
}
},
},
};
</script>
<style scoped>
.editable-row-operations a {
margin-right: 8px;
}
</style>
树形数据展示
表格支持树形数据的展示,当数据中有 children
字段时会自动展示为树形表格,如果不需要或配置为其他字段可以用 childrenColumnName
进行配置。
可以通过设置 indentSize
以控制每一层的缩进宽度。
注:暂不支持父子数据递归关联选择。
<template>
<a-table :columns="columns" :data-source="data" :row-selection="rowSelection" />
</template>
<script>
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
width: '12%',
},
{
title: 'Address',
dataIndex: 'address',
width: '30%',
key: 'address',
},
];
const data = [
{
key: 1,
name: 'John Brown sr.',
age: 60,
address: 'New York No. 1 Lake Park',
children: [
{
key: 11,
name: 'John Brown',
age: 42,
address: 'New York No. 2 Lake Park',
},
{
key: 12,
name: 'John Brown jr.',
age: 30,
address: 'New York No. 3 Lake Park',
children: [
{
key: 121,
name: 'Jimmy Brown',
age: 16,
address: 'New York No. 3 Lake Park',
},
],
},
{
key: 13,
name: 'Jim Green sr.',
age: 72,
address: 'London No. 1 Lake Park',
children: [
{
key: 131,
name: 'Jim Green',
age: 42,
address: 'London No. 2 Lake Park',
children: [
{
key: 1311,
name: 'Jim Green jr.',
age: 25,
address: 'London No. 3 Lake Park',
},
{
key: 1312,
name: 'Jimmy Green sr.',
age: 18,
address: 'London No. 4 Lake Park',
},
],
},
],
},
],
},
{
key: 2,
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
];
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
onSelect: (record, selected, selectedRows) => {
console.log(record, selected, selectedRows);
},
onSelectAll: (selected, selectedRows, changeRows) => {
console.log(selected, selectedRows, changeRows);
},
};
export default {
data() {
return {
data,
columns,
rowSelection,
};
},
};
</script>
可展开
当表格内容较多不能一次性完全展示时。
<template>
<a-table :columns="columns" :data-source="data">
<a slot="action" slot-scope="text" href="javascript:;">Delete</a>
<p slot="expandedRowRender" slot-scope="record" style="margin: 0">
{{ record.description }}
</p>
</a-table>
</template>
<script>
const columns = [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Age', dataIndex: 'age', key: 'age' },
{ title: 'Address', dataIndex: 'address', key: 'address' },
{ title: 'Action', dataIndex: '', key: 'x', scopedSlots: { customRender: 'action' } },
];
const data = [
{
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.',
},
{
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.',
},
{
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.',
},
];
export default {
data() {
return {
data,
columns,
};
},
};
</script>
固定头和列
适合同时展示有大量数据和数据列。
若列头与内容不对齐或出现列重复,请指定固定列的宽度
width
。如果指定width
不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。
建议指定scroll.x
为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过scroll.x
。
<template>
<a-table :columns="columns" :data-source="data" :scroll="{ x: 1500, y: 300 }">
<a slot="action" slot-scope="text">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>
固定列
对于列数很多的数据,可以固定前后的列,横向滚动查看其它数据,需要和 scroll.x
配合使用。
若列头与内容不对齐或出现列重复,请指定固定列的宽度
width
。如果指定width
不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。
建议指定scroll.x
为大于表格宽度的固定值或百分比。注意,且非固定列宽度之和不要超过scroll.x
。
<template>
<a-table :columns="columns" :data-source="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>
固定表头
方便一页内展示大量数据。
需要指定 column 的
width
属性,否则列头和内容可能不对齐。如果指定width
不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。
<template>
<a-table
:columns="columns"
:data-source="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>
表头分组
columns[n]
可以内嵌 children
,以渲染分组表头。
<template>
<a-table
:columns="columns"
:data-source="data"
bordered
size="middle"
:scroll="{ x: 'calc(700px + 50%)', 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',
width: 200,
},
{
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>
筛选和排序
对某一列数据进行筛选,使用列的 filters
属性来指定需要筛选菜单的列,onFilter
用于筛选当前数据,filterMultiple
用于指定多选和单选。
对某一列数据进行排序,通过指定列的 sorter
函数即可启动排序按钮。sorter: function(rowA, rowB) { ... }
, rowA、rowB 为比较的两个行数据。sortDirections: ['ascend' | 'descend']
改变每列可用的排序方式,切换排序时按数组内容依次切换,设置在 table props 上时对所有列生效。
使用 defaultSortOrder
属性,设置列的默认排序顺序。
<template>
<a-table :columns="columns" :data-source="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,
sortDirections: ['descend'],
},
{
title: 'Age',
dataIndex: 'age',
defaultSortOrder: 'descend',
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,
sortDirections: ['descend', 'ascend'],
},
];
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>
嵌套子表格
展示每行数据更详细的信息。
<template>
<a-table :columns="columns" :data-source="data" class="components-table-demo-nested">
<a slot="operation" slot-scope="text">Publish</a>
<a-table
slot="expandedRowRender"
slot-scope="text"
:columns="innerColumns"
:data-source="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>Pause</a>
<a>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> 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>
可控的筛选和排序
使用受控属性对筛选和排序状态进行控制。
- columns 中定义了 filteredValue 和 sortOrder 属性即视为受控模式。
- 只支持同时对一列进行排序,请保证只有一列的 sortOrder 属性是生效的。
- 务必指定
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" :data-source="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,
ellipsis: true,
},
{
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,
ellipsis: true,
},
];
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>
选择和操作
选择后进行操作,完成后清空选择,通过 rowSelection.selectedRowKeys
来控制选中项。
<template>
<div>
<div style="margin-bottom: 16px">
<a-button type="primary" :disabled="!hasSelected" :loading="loading" @click="start">
Reload
</a-button>
<span style="margin-left: 8px">
<template v-if="hasSelected">
{{ `Selected ${selectedRowKeys.length} items` }}
</template>
</span>
</div>
<a-table
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
:columns="columns"
:data-source="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>
自定义选择项
通过 rowSelection.selections
自定义选择项,默认不显示下拉选项,设为 true
时显示默认选择项。
<template>
<a-table :row-selection="rowSelection" :columns="columns" :data-source="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>
可选择
第一列是联动的选择框。
默认点击 checkbox 触发选择行为
<template>
<a-table :row-selection="rowSelection" :columns="columns" :data-source="data">
<a slot="name" slot-scope="text">{{ 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() {
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>
紧凑型
两种紧凑型的列表,小型列表只用于对话框内。
<template>
<div id="components-table-demo-size">
<h4>Middle size table</h4>
<a-table :columns="columns" :data-source="data" size="middle" />
<h4>Small size table</h4>
<a-table :columns="columns" :data-source="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>
template 风格的 API
使用 template 风格的 API
这个只是一个描述
columns
的语法糖,所以你不能用其他组件去包裹Column
和ColumnGroup
。
<template>
<a-table :data-source="data">
<a-table-column-group>
<span slot="title" style="color: #1890ff">Name</span>
<a-table-column key="firstName" data-index="firstName">
<span slot="title" style="color: #1890ff">First Name</span>
</a-table-column>
<a-table-column key="lastName" title="Last Name" data-index="lastName" />
</a-table-column-group>
<a-table-column key="age" title="Age" data-index="age" />
<a-table-column key="address" title="Address" data-index="address" />
<a-table-column key="tags" title="Tags" data-index="tags">
<template slot-scope="tags">
<span>
<a-tag v-for="tag in tags" :key="tag" color="blue">{{ tag }}</a-tag>
</span>
</template>
</a-table-column>
<a-table-column key="action" title="Action">
<template slot-scope="text, record">
<span>
<a>Action 一 {{ record.firstName }}</a>
<a-divider type="vertical" />
<a>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>
可伸缩列
集成 vue-draggable-resizable 来实现可伸缩列。
<template>
<a-table bordered :columns="columns" :components="components" :data-source="data">
<template v-slot:action>
<a href="javascript:;">Delete</a>
</template>
</a-table>
</template>
<script>
import Vue from 'vue';
import VueDraggableResizable from 'vue-draggable-resizable';
Vue.component('vue-draggable-resizable', VueDraggableResizable);
const columns = [
{
title: 'Date',
dataIndex: 'date',
width: 200,
},
{
title: 'Amount',
dataIndex: 'amount',
width: 100,
},
{
title: 'Type',
dataIndex: 'type',
width: 100,
},
{
title: 'Note',
dataIndex: 'note',
width: 100,
},
{
title: 'Action',
key: 'action',
scopedSlots: { customRender: 'action' },
},
];
const data = [
{
key: 0,
date: '2018-02-11',
amount: 120,
type: 'income',
note: 'transfer',
},
{
key: 1,
date: '2018-03-11',
amount: 243,
type: 'income',
note: 'transfer',
},
{
key: 2,
date: '2018-04-11',
amount: 98,
type: 'income',
note: 'transfer',
},
];
const draggingMap = {};
columns.forEach(col => {
draggingMap[col.key] = col.width;
});
const draggingState = Vue.observable(draggingMap);
const ResizeableTitle = (h, props, children) => {
let thDom = null;
const { key, ...restProps } = props;
const col = columns.find(col => {
const k = col.dataIndex || col.key;
return k === key;
});
if (!col.width) {
return <th {...restProps}>{children}</th>;
}
const onDrag = x => {
draggingState[key] = 0;
col.width = Math.max(x, 1);
};
const onDragstop = () => {
draggingState[key] = thDom.getBoundingClientRect().width;
};
return (
<th {...restProps} v-ant-ref={r => (thDom = r)} width={col.width} class="resize-table-th">
{children}
<vue-draggable-resizable
key={col.key}
class="table-draggable-handle"
w={10}
x={draggingState[key] || col.width}
z={1}
axis="x"
draggable={true}
resizable={false}
onDragging={onDrag}
onDragstop={onDragstop}
></vue-draggable-resizable>
</th>
);
};
export default {
name: 'App',
data() {
this.components = {
header: {
cell: ResizeableTitle,
},
};
return {
data,
columns,
};
},
};
</script>
<style lang="less">
.resize-table-th {
position: relative;
.table-draggable-handle {
height: 100% !important;
bottom: 0;
left: auto !important;
right: -5px;
cursor: col-resize;
touch-action: none;
}
}
</style>
API
Table
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
tableLayout | 表格元素的 table-layout 属性,设为 fixed 表示内容不会影响列的布局 | - | ‘auto’ | ‘fixed’ | 无 固定表头/列或使用了 column.ellipsis 时,默认值为 fixed | 1.5.0 |
bordered | 是否展示外边框和列边框 | boolean | false | |
childrenColumnName | 指定树形结构的列名 | string[] | children | |
columns | 表格列的配置描述,具体项见下表 | array | - | |
components | 覆盖默认的 table 元素 | object | - | |
dataSource | 数据数组 | any[] | ||
defaultExpandAllRows | 初始时,是否展开所有行 | boolean | false | |
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 | 通过点击行来展开子行 | boolean | false | |
expandIconColumnIndex | 展开的图标显示在哪一列,如果没有 rowSelection ,默认显示在第一列,否则显示在选择框后面 | number | ||
footer | 表格尾部 | Function(currentPageData)|slot-scope | ||
indentSize | 展示树形数据时,每层缩进的宽度,以 px 为单位 | number | 15 | |
loading | 页面是否加载中 | boolean|object | false | |
locale | 默认文案设置,目前包括排序、过滤、空数据文案 | object | filterConfirm: ‘确定’ filterReset: ‘重置’ emptyText: ‘暂无数据’ | |
pagination | 分页器,参考配置项或 pagination文档,设为 false 时不展示和进行分页 | object | ||
rowClassName | 表格行的类名 | Function(record, index):string | - | |
rowKey | 表格行 key 的取值,可以是字符串或一个函数 | string|Function(record):string | ‘key’ | |
rowSelection | 列表项是否可选择,配置项 | object | null | |
scroll | 设置横向或纵向滚动,也可用于指定滚动区域的宽和高,建议为 x 设置一个数字,如果要设置为 true ,需要配合样式 .ant-table td { white-space: nowrap; } | { x: number | true, y: number } | - | |
showHeader | 是否显示表头 | boolean | true | |
size | 表格大小 | default | middle | small | default | |
title | 表格标题 | Function(currentPageData)|slot-scope | ||
customHeaderRow | 设置头部行属性 | Function(column, index) | - | |
customRow | 设置行属性 | Function(record, index) | - | |
getPopupContainer | 设置表格内各类浮层的渲染节点,如筛选菜单 | (triggerNode) => HTMLElement | () => TableHtmlElement | 1.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语法。
<Table
customRow={(record) => {
return {
props: {
xxx... //属性
},
on: { // 事件
click: (event) => {}, // 点击行
dblclick: (event) => {},
contextmenu: (event) => {},
mouseenter: (event) => {}, // 鼠标移入行
mouseleave: (event) => {}
},
};
)}
customHeaderRow={(column) => {
return {
on: {
click: () => {}, // 点击表头行
}
};
)}
/>
Column
列描述数据对象,是 columns 中的一项,Column 使用相同的 API。
参数 | 说明 | 类型 | 默认值 | 版本 |
---|---|---|---|---|
align | 设置列内容的对齐方式 | ‘left’ | ‘right’ | ‘center’ | ‘left’ | |
ellipsis | 超过宽度将自动省略,暂不支持和排序筛选一起使用。 设置为 true 时,表格布局将变成 tableLayout=”fixed” 。 | boolean | false | 1.5.0 |
colSpan | 表头列合并,设置为 0 时,不渲染 | number | ||
dataIndex | 列数据在数据项中对应的 key,支持 a.b.c 的嵌套写法 | string | - | |
defaultFilteredValue | 默认筛选值 | string[] | - | 1.5.0 |
filterDropdown | 可以自定义筛选菜单,此函数只负责渲染图层,需要自行编写各种交互 | VNode | slot-scope | - | |
filterDropdownVisible | 用于控制自定义筛选菜单是否可见 | boolean | - | |
filtered | 标识数据是否经过过滤,筛选图标会高亮 | boolean | false | |
filteredValue | 筛选的受控属性,外界可用此控制列的筛选状态,值为已筛选的 value 数组 | string[] | - | |
filterIcon | 自定义 filter 图标。 | VNode | (filtered: boolean, column: Column) => vNode |slot |slot-scope | false | |
filterMultiple | 是否多选 | boolean | true | |
filters | 表头的筛选菜单项 | object[] | - | |
fixed | 列是否固定,可选 true (等效于 left) ‘left’ ‘right’ | boolean|string | false | |
key | Vue 需要的 key,如果已经设置了唯一的 dataIndex ,可以忽略这个属性 | string | - | |
customRender | 生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据,行索引,@return 里面可以设置表格行/列合并,可参考 demo 表格行/列合并 | Function(text, record, index) {}|slot-scope | - | |
sorter | 排序函数,本地排序使用一个函数(参考 Array.sort 的 compareFunction),需要服务端排序可设为 true | Function|boolean | - | |
sortOrder | 排序的受控属性,外界可用此控制列的排序,可设置为 ‘ascend’ ‘descend’ false | boolean|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 | - | |
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 | 去掉『全选』『反选』两个默认选项 | boolean | false |
selectedRowKeys | 指定选中项的 key 数组,需要和 onChange 进行配合 | string[] | [] |
selections | 自定义选择配置项, 设为 true 时使用默认选择项 | object[]|boolean | true |
type | 多选/单选,checkbox or radio | string | checkbox |
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
自定义选择配置项
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
key | Vue 需要的 key,建议设置 | string | - |
text | 选择项显示的文字 | string|VNode | - |
onSelect | 选择项点击回调 | Function(changeableRowKeys) | - |
注意
在 Table 中,dataSource
和 columns
里的数据值都需要指定 key
值。对于 dataSource
默认将每列数据的 key
属性作为唯一的标识。
如果你的数据没有这个属性,务必使用 rowKey
来指定数据列的主键。若没有指定,控制台会出现缺少 key 的提示,表格组件也会出现各类奇怪的错误。
// 比如你的数据主键是 uid
return <Table rowKey="uid" />;
// 或
return <Table rowKey={record => record.uid} />;