# antdv 中 table 组件
# 1. 介绍
ant-design-vue (4.1.2) 中的 table 组件
# 2. 注意
- 设置 resizable 时,需要留一列不设置 resizable,否则会造成拖拽异常
- 设置 width 时,需要留一列不设置 width,否则会造成表头与内容对不齐
# 3. 去掉分页器
示例:
<template>
<a-table
:pagination="false"
>
</a-table>
</template>
参考:
# 4. 列宽可拖拽调整
说明:
- 用于固定宽度的表格,列设置的宽度是 像素值
- 配合
ellipsis: true
,表头、单元格 不会折行 - 至少需要一列(通常是最后一列) 不设置宽度且不可拖拽
代码:
<template>
<a-table
:columns="columns"
@resizeColumn="handleResizeColumn"
>
</a-table>
</template>
<script>
export default {
data() {
return {
columns: [
{ title: 'name', /* ... */ width: 200, ellipsis: true, resizable: true },
{ title: 'age', /* ... */ width: 200, ellipsis: true, resizable: true },
{ title: 'gender', /* ... */ ellipsis: true, resizable: false },
],
};
},
methods: {
handleResizeColumn(width, column) {
column.width = width;
},
}
};
</script>
# 5. 单击选中行
<template>
<a-table
:data-source="list"
:custom-row="customRow"
:row-selection="rowSelection"
rowKey="userId"
>
</a-table>
</template>
<script>
export default {
data() {
return {
list: [
{ userId: '001', userName: 'zhangsan', /* ... */ },
// ...
],
rowSelection: {
type: 'radio',
selectedRowKeys: [],
onChange: this.onSelectChange,
},
};
},
methods: {
customRow(record, index) {
return {
onClick: () => {
this.onClickRow(record);
},
};
},
onClickRow(record) {
this.onSelectChange([record.userId], record);
},
onSelectChange(selectedRowKeys, record) {
this.rowSelection.selectedRowKeys = selectedRowKeys;
},
},
};
</script>
<style>
/* 隐藏 radio 那列 */
.ant-table-selection-column {
padding: 0!important;
}
.ant-table-selection-col {
width: 0!important;
}
.ant-radio-wrapper {
display: none;
}
</style>
# 6. 复选框和单选框的使用
说明:
- 需要指定 record 中的主键名称
- 无论是 checkbox 还是 radio,onChange 的方法签名不变
- onChange 只能获取当前分页已选择的记录
- 如果想跨分页多选,则需要根据 onSelect、onSelectAll 中的 selected 值 设置 selectedRowKeys
示例:
<template>
<a-table
row-key="userId"
:data-source="list"
:columns="columns"
:row-selection="{
type: 'checkbox', /* 'checkbox' | 'radio' */
columnWidth: 32,
selectedRowKeys,
onChange,
getCheckboxProps,
}"
>
...
</a-table>
</template>
<script>
export default {
data() {
return {
selectedRowKeys: [],
list: [
{ userId: '1', userName: 'zhangsan' },
]
}
},
methods: {
onChange(selectedRowKeys, selectedRows) {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
this.selectedRowKeys = selectedRowKeys;
},
getCheckboxProps(record) {
return {
// 全部默认禁止选中
// disabled: true,
// 禁用某些记录
disabled: record.status === 'disabled',
// defaultChecked: record.state == 1,
};
}
}
}
</script>
参考:
node_modules/ant-design-vue/es/table/interface.d.ts
node_modules/ant-design-vue/es/checkbox/interface.d.ts
# 7. 自定义渲染单元格
注意:
- 使用
bodyCell
插槽的话,customRender 会被覆盖
示例:
<template>
<a-table
:columns="columns"
>
<template #bodyCell="{ column }">
<!-- age 列上使用 customRender 不生效 -->
<template v-if="column.key === 'age'">
<CheckOutlined />
</template>
</template>
</a-table>
</template>
<script lang="tsx">
import { defineComponent } from 'vue';
export default defineComponent({
data() {
return {
columns: [
// ...
{
title: 'Sheet Name',
width: 100,
dataIndex: 'sheetName',
key: 'sheetName',
/**
* @param column - {title: 'Sheet Name', width: 100, dataIndex: 'sheetName', key: 'sheetName', customRender}
*/
customRender({ text, record, index, column }) {
/*
处理 tsx 报错误的问题:
tsconfig.json
"noImplicitAny": false,
*/
return (
<div>{ text }</div>
);
},
},
]
};
},
});
</script>
# 8. 表头排序功能
<template>
<a-table
:columns="columns"
:show-sorter-tooltip="false"
/>
</template>
<script lang="tsx">
import { defineComponent } from 'vue';
export default defineComponent({
data() {
return {
columns: [
// ...
{
title: 'Sheet Name',
width: 100,
dataIndex: 'sheetName',
key: 'sheetName',
sorter: (prevRecord, currRecord) => {
const result = prevRecord.sheetName > prevRecord.sheetName
return result ? 1 : -1;
}
},
]
};
},
});
</script>
# 9. 固定高度
说明:
- 设置的高度不是 数据表格整体的高度,仅仅是 记录的容器的高度
示例:
<template>
<a-table
:scroll={ y: '200px' }
>
</a-table>
</template>
# 10. 排序
示例:
<template>
<a-table
:columns="columns"
@change="handleChange"
/>
</template>
<script lang="ts">
import type { SorterResult } from 'ant-design-vue/es/table/interface';
export default {
data() {
return {
columns: [
{
title: 'Timestamp',
dataIndex: 'timeStamp',
key: 'timeStamp',
sorter: true, // 后台排序,侦听通过 change 事件
defaultSortOrder: 'descend', // null | 'ascend' | 'descend'
},
]
}
},
methods: {
handleChange(pagination, filters, sorter: SorterResult) {
const {
field, // timeStamp
order, // 'descend' | 'ascend' | null;
} = sorter;
}
}
}
</script>
# 11. 设置行的样式类
说明:
- 额外添加 样式类名称
示例:
<template>
<a-table
:row-class-name="rowClassName"
/>
</template>
<script lang="ts">
import type { SorterResult } from 'ant-design-vue/es/table/interface';
export default {
methods: {
rowClassName({ __status }: IRecord, index) {
if (__status === UploadStatus.Uploaded) {
return 'lw-is-uploaded';
}
if (__status === UploadStatus.NotUploaded) {
return 'lw-is-not-uploaded';
}
return '';
},
}
}
</script>
# 12. 设置单元格的样式
示例:
<template>
<a-table
:columns="columns"
/>
</template>
<script lang="ts">
export default {
data() {
return {
columns: [
{
title: 'Timestamp',
dataIndex: 'timeStamp',
key: 'timeStamp',
customCell: this.customCell,
},
]
}
},
methods: {
customCell(record) {
let className = '';
if (record.xyz === 0 ) {
className = 'lw-table-cell-danger';
}
return {
class: className,
}
},
}
}
</script>
# 13. 拖拽排序
说明:
- 通过 dnd 相关 API 完成行的拖拽排序
示例:
<template>
<a-table
class="a-table-dnd"
:custom-row="customRow"
/>
</template>
<script lang="ts">
interface IRecord {
[key: string]: string,
index: number,
}
export default {
data() {
return {
dnd: {
enabled: false,
sourceRecord: {} as IRecord,
targetRecord: {} as IRecord,
},
}
},
methods: {
customRow(record: IRecord, index: number) {
return {
// 鼠标移入
onMouseenter: (event: any) => {
event.target.draggable = this.dnd.enabled; // 让你要拖动的行可以拖动,默认不可以
},
// 开始拖拽
onDragstart: (event: MouseEvent) => {
event.stopPropagation();
this.dnd.sourceRecord = record;
},
// 拖动元素经过的元素
onDragover: (event: MouseEvent) => {
event.preventDefault();
},
// 拖动到达目标元素
onDragenter: (event: MouseEvent) => {
event.preventDefault();
event.stopPropagation();
// 此时 record 为进入的“行”的数据,高亮 进入的行
const rowElements = document.querySelectorAll('.a-table-dnd .ant-table-row');
Array.from(rowElements || []).forEach((rowElement, i) => {
if (i === index) {
rowElement.classList.add('ant-table-row-selected');
} else {
rowElement.classList.remove('ant-table-row-selected');
}
});
},
// 鼠标松开(如果在表格外松开,则不触发这个事件)
onDrop: (event: MouseEvent) => {
event.stopPropagation();
this.dnd.targetRecord = record;
// - 交换两个行
const { sourceRecord, targetRecord } = this.dnd;
const sourceIndex = this.LIST.findIndex((item) => item.index === sourceRecord.index);
const targetIndex = this.LIST.findIndex((item) => item.index === targetRecord.index);
this.LIST[sourceIndex] = targetRecord;
this.LIST[targetIndex] = sourceRecord;
this.LIST.forEach((item, i) => {
item.index = i + 1;
});
},
// 拖拽结束(无论是否在表格外松开鼠标,一定会调用)
onDragend() {
// 清除高亮效果
const rowElements = document.querySelectorAll('.a-table-dnd .ant-table-row');
Array.from(rowElements || []).forEach((rowElement) => {
rowElement.classList.remove('ant-table-row-selected');
});
},
};
},
}
}
</script>
参考:
# 14. 列过滤
示例:
<template>
<a-table
:columns="columns"
>
<template #customFilterIcon="{ column }">
<!--
column.filterList.length === 0
true: 显示高亮的 过滤图标,标志已设置过滤条件
false: 显示普通的 过滤图标
-->
</template>
<template #customFilterDropdown="{ confirm, column }" >
<!--
执行 confirm() 会关闭过滤容器弹窗
-->
<FilterPanel
v-model:value="column.filterList"
:field-title="column.title"
:field-name="column.key"
@confirm="confirmFilters(confirm)"
@reset="resetFilters(confirm)"
/>
</template>
</a-table>
</template>
<script lang="ts">
export default {
data() {
return {
columns: [
{
title: 'name', dataIndex: 'name', key: 'name',
customFilterDropdown: true, // antdv 的属性,标志该列 自定义过滤
filterList: [], // 自定义属性,用于存放过滤规则
},
]
}
},
methods: {
confirmFilters(closePanel: () => void) {
closePanel();
this.doFilterList();
},
resetFilters(closePanel: () => void) {
closePanel();
this.doFilterList();
},
doFilterList() {
const { columns } = this;
this.LIST = (this as any).result.filter((record) => {
const isMatched = columns.every((column: any) => {
const filterList: IFilterRecord[] = column.filterList || [];
return isMatchFilterList(record[column.key], filterList);
});
return isMatched;
});
},
}
}
</script>
上一篇: 下一篇:
本章目录