效果如图
后台返回的数据结构是树状结构,注意内嵌的最内层数组不要命名为children,否则antd会自动将表格变为可展开类表格,如果后台定义成了children字段,前端在渲染页面前将字段改名即可
第一步需要先把数组拆分成普通的数组
var data = [
{
id: 1,
name: "小组1",
list: [
{ id: 101, name1: "111" },
{ id: 102, name1: "222" },
{ id: 103, name1: "333" },
],
},
{
id: 2,
name: "小组2",
list: [
{ id: 201, name1: "qqq" },
{ id: 202, name1: "www" },
{ id: 203, name1: "aaz" },
],
},
{
id: 3,
name: "小组3",
list: [
{ id: 301, name1: "aaa" },
{ id: 302, name1: "bbb" },
],
},
]
// 假设上面这个数组是后台传给我们的数据
// 接收到数据后将数据拆分
data.forEach((i, index) => {
i.childLength = i.list.length; // 设置一个字段,即要跨多少行的数值
i.num = index + 1; // 保留小组的序号
i.list.forEach((a, index1) => {
a.childIndex = index1; // 根据childIndex来判断从哪行开始跨
});
});
data = data.flatMap((item) => {
return item.list.map((listItem) => ({
webId: item.id, // 由于有两个id,两个id都有各自的用处,需要将最外层的id改个字段名,否则只会保留最内层的id
...item, //其他字段保留
...listItem, //其他字段保留
}));
});
数组拆分完了后,设置表头
export default {
data() {
// columns需在data内定义,否则操作栏中的dom元素无法在页面渲染
const columns = [
{
title: "序号",
dataIndex: "num", // 小组序号
align: "center",
width: 60,
customRender: (text, row) => {
const obj = {
children: text, // text即dataIndex所填写的字段值
attrs: {},
};
if (row.childIndex == 0) { // 表示从第一个成员那行开始跨行
obj.attrs.rowSpan = row.childLength;
} else {
obj.attrs.rowSpan = 0;
}
return obj;
},
},
{
title: "小组",
dataIndex: "name",
align: "center",
customRender: (text, row) => {
const obj = {
children: text,
attrs: {},
};
if (row.childIndex == 0) {
obj.attrs.rowSpan = row.childLength;
} else {
obj.attrs.rowSpan = 0;
}
return obj;
},
},
{
title: "成员",
dataIndex: "name1",
width: 100,
align: "center",
},
{
title: "职务",
dataIndex: "name2",
width: 90,
align: "center",
},
{
title: "性别",
dataIndex: "name3",
align: "center",
},
{
title: "联系方式",
dataIndex: "name4",
align: "center",
},
{
title: "备注",
dataIndex: "name7",
align: "center",
},
{
title: "操作",
align: "center",
width: 200,
customRender: (text, record) => {
const obj = {
children: (
<div>
<span
class="editBtn"
onClick={() => this.editInfo(record.webId)}
>
编辑
</span>
<a-popconfirm
placement="bottomRight"
title="确定删除?"
ok-text="确定"
cancel-text="取消"
onConfirm={() => this.onDelete(record.webId)}
>
<span class="delBtn">删除</span>
</a-popconfirm>
</div>
),
attrs: {},
};
if (record.childIndex == 0) {
obj.attrs.rowSpan = record.childLength;
} else {
obj.attrs.rowSpan = 0;
}
return obj;
},
},
];
return {
data: [
{
id: 1,
name: "小组1",
list: [
{ id: 101, name1: "111" },
{ id: 102, name1: "222" },
{ id: 103, name1: "333" },
],
},
{
id: 2,
name: "小组2",
list: [
{ id: 201, name1: "qqq" },
{ id: 202, name1: "www" },
],
},
{
id: 3,
name: "小组3",
list: [{ id: 301, name1: "aaa" }],
},
],
};
},
mounted(){
this.getData();
},
methods:{
getData(){
// 在此处调用接口获取后台的表格数据,并将数据拆分
},
editInfo(){
// 编辑按钮的点击事件
},
onDelete(){
// 删除按钮的点击事件
},
},
}
customRender与插槽scopedSlots无法同时设置,所以只能在customRender设置按钮dom元素与点击事件,且columns需在data内定义,如果写在data外,无法渲染dom元素,还会报错[Vue warn]: Error in render: "ReferenceError: h is not defined"
表格的html代码没有什么变化,与官网一致
<a-table
:columns="columns"
:data-source="data"
:pagination="pagination"
:row-key="(record) => record.id"
@change="handleTableChange"
>
</a-table>