效果图如下:
在本文章中,我会讲一点代码的逻辑,仅供参考,因为代码是活的
话不多说我们开始!
首先是el-table嵌套el-table
这里要注意两个地方
1. 主table
1.1@select-all="mainSelectAll" -->主table的全选
1.2@select="mainSelect" -->主table的单选
1.3 :ref="main" -->主table的ref对象命名
2. 子table
2.1@select="subSelect" -->子单选
2.2@select-all="subSelectAll" -->子全选 :ref="'sub' + scope.$index"
<el-table v-loading="loading" :data="personList" @selection-change="handleSelectionChange" ref="main"
@select-all="mainSelectAll" @select="mainSelect">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="expand">
<template slot-scope="scope">
<el-table :data="scope.row.attachmentList" border stripe size="small" :show-header="false"
:ref="'sub' + scope.$index" @select="subSelect" @select-all="subSelectAll">
<el-table-column type="selection" width="100" align="center" />
<el-table-column prop="attachmentName" label="证件名称" width="350" show-overflow-tooltip>
<template slot-scope="props">
<span style="color:red">证件名称:</span>{{ props.row.attachmentName }}
</template>
</el-table-column>
<el-table-column prop="attachmentTypeName" label="证件类型" width="350" show-overflow-tooltip>
<template slot-scope="props">
<span style="color:red">证件类型:</span>{{ props.row.attachmentTypeName }}
</template>
</el-table-column>
<el-table-column prop="validityDate" label="证件到期时间" width="350" show-overflow-tooltip>
<template slot-scope="props">
<span style="color:red">证件到期时间:</span>{{ props.row.validityDate }}
</template>
</el-table-column>
<el-table-column prop="updateTime" label="最后更新时间" width="350" show-overflow-tooltip>
<template slot-scope="props">
<span style="color:red">最后更新时间:</span>{{ props.row.updateTime }}
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
</el-table>
下面开始讲解各方法!!
在讲解各方法前,需要先理解三个东西!
1. toggleRowExpansion(row, expanded);
这个方法是展开表格,当我选中主table的时候,自动将子table展开
2. clearSelection();
用于取消全选,清空选择
3.toggleRowSelection(row, selected);
用于选中某条数据,row必须为单条数据(类似map形式),selected是否选中(true/false)
1. 主table的全选mainSelectAll方法
1. 取消全选时,循环main的数据拿到下标,将子table的所有全部选择都清空掉:clearSelection
2. 全选时将循环我personList(主表的数据),然后
2.1:展开子table:toggleRowExpansion()方法
2.2:如果selection有东西,执行主table选中/子table全选方法
2.3:如果没有:执行cleanIs();清空方法
//主table全选
mainSelectAll(selection) {
if (selection.length == 0) {
var datas = this.$refs.main.data;
datas.forEach((item, index) => {
this.$refs[`sub${index}`].clearSelection()
});
} else {
this.personList.forEach(async (item, index) => {
await this.$refs['main'].toggleRowExpansion(item, true)
if (selection.length !== 0) {
let ls = new Array();
ls.push(item);
this.mainSelect(ls, item)
this.subSelectAll(item.subList, index)
} else {
this.cleanIs(null, item)
}
this.$refs[`sub${index}`].clearSelection()
});
}
},
2. 主table的单选mainSelect方法
1. 参数讲解:
1.1:selection->勾选过的数据
1.2:row->当前点击勾选框的数据
2. 判断主table是否选中:isCheck
2.1:查看selection是否存在row数据,如果没有就说明这条记录是取消
3. this.subIds
subIds用于回显!!!!!!!!!!
//主table的单选
mainSelect(selection, row) {
const isCheck = selection.includes(row);
this.personList.forEach((item, index) => {
if (item.id === row.id) {
this.$refs.main.toggleRowExpansion(item, true);
const tempList = row.attachmentList;
this.$nextTick(() => {
if (tempList.length !== 0) {
tempList.forEach((childItem) => {
this.selectAllChildMap.set(index, item);
this.$refs.main.toggleRowSelection(item, isCheck);
this.$refs[`sub${index}`].toggleRowSelection(childItem, isCheck);
if (isCheck) {
this.subIds.push(childItem.id);
} else {
this.subIds.pop(childItem.id);
}
})
}
})
}
})
if (isCheck) {
this.validIs(row.attachmentList);
} else {
this.cleanIs(null, row);
}
},
3. 子table的全选subSelectAll()方法
1. 参数讲解
1.1:selection -> 勾选过的数据
1.2:clickIndex -> 下标(下标用于其他方法调用时,传进的参数)
//子表格勾选 --->联动一级表格
subSelectAll(selection, clickIndex) {
if (selection != null && selection.length > 0) {
const fatherRow = this.personList.find(item => {
return item.id === selection[0].parentId
})
this.selectAllChildMap.set(clickIndex, fatherRow)
this.$refs.main.toggleRowSelection(this.selectAllChildMap.get(clickIndex), true)
// 非空时候 检验明细是否存在
this.validIs(selection)
} else {
this.cleanIs(clickIndex, null);
this.$refs.main.toggleRowSelection(this.selectAllChildMap.get(clickIndex), false)
this.selectAllChildMap.delete(clickIndex)
};
},
4. 子table的单选subSelect()方法
这里需要注意的是 我会循环selection 判断我本条数据是否存在,如果存在,flag为true;
1. 如果flag为true,则证明本条记录需要回显,会把id添加到全局变量的subIds里;
2. 如果flag为false,则需要把subIds里对应的记录删掉(本人不善于前端代码,所以用了最笨的方法就是循环重新赋值)
//子table单选
subSelect(selection, row) {
const isCheck = selection.length > 0
this.personList.forEach((item, index) => {
if (item.id == row.tableId) {
this.selectAllChildMap.set(index, item)
this.$refs.main.toggleRowSelection(item, isCheck)
}
});
let flag = false;
selection.forEach((item, index) => {
if (item.id == row.id) {
//说明存在
flag = true;
}
})
if (flag) {
this.subIds.push(row.id);
} else {
let ls = new Array();
this.subIds.forEach(function(item, index, arr) {
if (item == row.id) {
} else {
ls.push(item);
}
});
this.subIds = ls;
}
},
5. 其余代码(校验/清空/data里声明的参数 方面代码)
//data里需要声明的参数:
data() {
return {
selectAllChildMap: new Map(),
ruleForm: {
items: []
},
}
---------------------------------------------------------------------------------
//一级勾选框和子级头部勾选框检验
validIs(selection) {
// 非空时候 检验明细是否存在
if (this.ruleForm.items.length === 0) {
this.ruleForm.items.push(...selection)
} else {
let ids2 = this.ruleForm.items.map(f => f.id)
selection.forEach(f => {
if (ids2.indexOf(f.id) !== -1) {
delete this.ruleForm.items[ids2.indexOf(f.id)]
}
})
this.ruleForm.items = this.ruleForm.items.filter(f => f.id)
ids2 = this.ruleForm.items.map(f => f.id)
this.ruleForm.items.push(...selection)
}
},
-----------------------------------------------------------------------------------------
//一级勾选框和子级头部勾选清空方法
cleanIs(clickIndex, fatherRow) {
const childIdList = new Array();
if (clickIndex != null && clickIndex >= 0) {
childIdList.push(this.personList[clickIndex].attachmentList);
} else {
if (fatherRow != null && fatherRow != undefined) {
childIdList.push(fatherRow.attachmentList);
}
}
let ids2 = this.ruleForm.items.map(f => f.id)
childIdList.forEach(f => {
if (ids2.indexOf(f) !== -1) {
delete this.ruleForm.items[ids2.indexOf(f)]
}
})
this.ruleForm.items = this.ruleForm.items.filter(f => f.id)
ids2 = this.ruleForm.items.map(f => f.id)
},
6. 数据结构
主table的personList就是这6条数据
每条数据内部有一个attachmentList:为我的子table的数据
7. 小结
1. 一定要理解最开始说的三个方法
toggleRowExpansion
clearSelection
toggleRowSelection
2. 数据回显的subIds:一定是放在主/子table的单选方法里执行的,因为你全选时,会调用单选方法