- Table 表格
- 何时使用
- 如何使用
- 代码演示
- 远程加载数据
- 基本用法
- 带边框
- 表格行/列合并
- 自定义筛选菜单
- 可编辑单元格
- 可编辑行
- 树形数据展示
- 可展开
- 固定头和列
- 固定列
- 固定表头
- 表头分组
- 筛选和排序
- 嵌套子表格
- 可控的筛选和排序
- 选择和操作
- 自定义选择项
- 可选择
- 紧凑型
- template 风格的 API
- API
- Table
- 事件
- customRow 用法
- Column
- ColumnGroup
- pagination
- rowSelection
- selection
- 注意
Table 表格
展示行列数据。
何时使用
- 当有大量结构化的数据需要展现时;
- 当需要对数据进行排序、搜索、分页、自定义操作等复杂行为时。
如何使用
指定表格的数据源 dataSource 为一个数组。
代码演示

远程加载数据
这个例子通过简单的 ajax 读取方式,演示了如何从服务端读取并展现数据,具有筛选、排序等功能以及页面 loading 效果。开发者可以自行接入其他数据处理方式。另外,本例也展示了筛选排序功能如何交给服务端实现,列不需要指定具体的 onFilter 和 sorter 函数,而是在把筛选和排序的参数发到服务端来处理。注意,此示例使用 模拟接口,展示数据可能不准确,请打开网络面板查看请求。
<template><a-table :columns="columns":rowKey="record => record.login.uuid":dataSource="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 {mounted() {this.fetch();},data() {return {data: [],pagination: {},loading: false,columns,}},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 = truereqwest({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" :dataSource="data"><a slot="name" slot-scope="text" href="javascript:;">{{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" color="blue" :key="tag">{{tag}}</a-tag></span><span slot="action" slot-scope="text, record"><a href="javascript:;">Invite 一 {{record.name}}</a><a-divider type="vertical" /><a href="javascript:;">Delete</a><a-divider type="vertical" /><a href="javascript:;" 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>

带边框
添加表格边框线,页头和页脚。
<template><a-table :columns="columns" :dataSource="data" bordered><template slot="name" slot-scope="text"><a href="javascript:;">{{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" :dataSource="data" bordered><template slot="name" slot-scope="text"><a href="javascript:;">{{text}}</a></template><template slot="action" slot-scope="text, record"><span><a href="javascript:;">Action 一 {{record.name}}</a><a-divider type="vertical" /><a href="javascript:;">Delete</a><a-divider type="vertical" /><a href="javascript:;" class="ant-dropdown-link">More actions <a-icon type="down" /></a></span></template></a-table></template><script>// In the fifth row, other columns are merged into first column// by setting it's colSpan to be 0const 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 cellif (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 :dataSource="data" :columns="columns"><div slot="filterDropdown" slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }" class='custom-filter-dropdown'><a-inputv-ant-ref="c => searchInput = c":placeholder="`Search ${column.dataIndex}`":value="selectedKeys[0]"@change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"@pressEnter="() => handleSearch(selectedKeys, confirm)"style="width: 188px; margin-bottom: 8px; display: block;"/><a-buttontype='primary'@click="() => handleSearch(selectedKeys, confirm)"icon="search"size="small"style="width: 90px; margin-right: 8px">Search</a-button><a-button@click="() => handleReset(clearFilters)"size="small"style="width: 90px">Reset</a-button></div><a-icon slot="filterIcon" slot-scope="filtered" type='search' :style="{ color: filtered ? '#108ee9' : undefined }" /><template slot="customRender" slot-scope="text"><span v-if="searchText"><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,columns: [{title: 'Name',dataIndex: 'name',key: 'name',scopedSlots: {filterDropdown: 'filterDropdown',filterIcon: 'filterIcon',customRender: 'customRender',},onFilter: (value, record) => record.name.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.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.toLowerCase().includes(value.toLowerCase()),onFilterDropdownVisibleChange: (visible) => {if (visible) {setTimeout(() => {this.searchInput.focus()})}},}],}},methods: {handleSearch (selectedKeys, confirm) {confirm()this.searchText = selectedKeys[0]},handleReset (clearFilters) {clearFilters()this.searchText = ''},},}</script><style scoped>.custom-filter-dropdown {padding: 8px;