效果图如下:
声明:
代码参考与两位博主:
1./5fuuyvue+element-ui 表格嵌套表格实现和勾选问题解决_vue表格嵌套表格_陈怂怂的博客-CSDN博客/5fuuy
2.【el-table嵌套父子勾选 并实现数据携带勾选的到另一张表中 】_el-tab表格勾选数据到另外一张表_️ht的博客-CSDN博客
感谢两位博主分享,不过有一些问题,例如单选,数据回显方面我做了详解和优化
在本文章中,我会讲一点代码的逻辑,仅供参考,因为代码是活的,人是死的
(如果人是活的,代码怎么可能是死的呢)
话不多说我们开始!
首先是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"-->子全选
2.3:ref="'sub' + scope.$index"-->子table的ref对象命名(加上了下标)
<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 > 0this.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的单选方法里执行的,因为你全选时,会调用单选方法
3. 如果你看到这里,说明你还是仔细读了这篇文章,如果有什么问题,或者我有什么问题! 请随时提问指出!
谢谢大家!