element ui 树状表格选择父节点子节点全选,子节点不全选父节点半选

您所在的位置:网站首页 eltable树形结构父节点没数据 element ui 树状表格选择父节点子节点全选,子节点不全选父节点半选

element ui 树状表格选择父节点子节点全选,子节点不全选父节点半选

2024-07-10 12:50| 来源: 网络整理| 查看: 265

最近开发了一个需求,element 树状表格,表格全选时所有项(包括所有子节点)都选中,选中树状表格父节点时,这个父节点下所有子节点也都要选中,如果某个父节点下的所有子节点没有全部,则这个父节点处于半选状态

效果图:

1.HTML

2.JS

export default { name: "index", data() { return { // 遮罩层 loading: true, // 选中数组 ids: [], // 非单个禁用 single: true, // 非多个禁用 multiple: true, // 总条数 total: 0, // 运单管理表格数据 orderList: [], // 查询参数 queryParams: { }, page: { pageNum: 1, pageSize: 15, }, oneProductIsSelect:[], isFun:false }; }, created() { this.getList(); }, methods: { // 查询列表 getList() { this.loading = true; listOrder(this.queryParams, this.page).then((response) => { this.orderList=response.rows //这一步是为了将父和子之间有联系,给子定义一个taskId,将子的taskId和父的id一致 this.orderList.forEach((item, index) => { if (item.children) { item.children.forEach((cItem, cIndex) => { cItem.taskId = item.id; }); } }); // 由于后端返回的数组id不唯一(父里的id和其中一个子的id一样),然后:row-key='id'里面的id要是唯一值,所以处理了一下,将父的id改变,将数组里面的id都唯一,当然,你可以跟后端商量一下,返回给你一个唯一值,这个处理代码就可以省略了 this.orderList = this.orderList.map((item,index)=>{ return{ ...item, uuid:`${index}-${this.guid()}` } }) this.total = response.total; //页数 this.loading = false; // 遮罩层 this.initData(this.orderList) }); }, //生成唯一ID guid() { return Number( Math.random().toString().substr(3, 3) + Date.now() ).toString(36); }, //row-key唯一值 rowKeyFunc(row){ if(row.uuid){ return row.uuid }else { return row.id } }, //初始化数据,将数据都用isSelect标记一下,isSelect为false不选中、true选中、half半选 initData(data) { data.forEach((item) => { item.isSelect = false; //默认为不选中 if (item.children && item.children.length) { this.initData(item.children); } }); }, // 判断是不是全选 checkIsAllSelect() { this.oneProductIsSelect = []; this.orderList.forEach((item) => { this.oneProductIsSelect.push(item.isSelect); }); //判断一级产品是否是全选.如果一级产品全为true,则设置为取消全选,否则全选 let isAllSelect = this.oneProductIsSelect.every((selectStatusItem) => { return true == selectStatusItem; }); return isAllSelect; }, // 全选或者全不选(这个是祖父的勾选) selectAllFun(selection) { let isAllSelect = this.checkIsAllSelect(); this.orderList.forEach((item) => { item.isSelect = isAllSelect; this.$refs.table.toggleRowSelection(item, !isAllSelect); this.selectFun(selection, item); }); }, selectFun(selection, row) { this.setRowIsSelect(row); }, setRowIsSelect(row) { //当点击父级点复选框时,当前的状态可能为未知状态,所以当前行状态设为false并选中,即可实现子级点全选效果 if (row.isSelect == "half") { row.isSelect = false; this.$refs.table.toggleRowSelection(row, true); } row.isSelect = !row.isSelect; //判断操作的是子级点复选框还是父级点复选框,如果是父级点,则控制子级点的全选和不全选 if (row.children && row.children.length > 0) { row.children.forEach((item) => { item.isSelect = row.isSelect; this.$refs.table.toggleRowSelection(item, row.isSelect); }); } else { //操作的是子节点 1、获取父节点 2、判断子节点选中个数,如果全部选中则父节点设为选中状态,如果都不选中,则为不选中状态,如果部分选择,则设为不明确状态 let parentId = row.taskId; this.orderList.forEach((item) => { let isAllSelect = []; if (item.id == parentId) { if(item.children){ item.children.forEach((databaseSourceListItem) => { isAllSelect.push(databaseSourceListItem.isSelect); }); } if ( isAllSelect.every((selectItem) => { return true == selectItem; }) ) { item.isSelect = true; this.$refs.table.toggleRowSelection(item, true); } else if ( isAllSelect.every((selectItem) => { return false == selectItem; }) ) { item.isSelect = false; this.$refs.table.toggleRowSelection(item, false); } else{ item.isSelect ="half"; } } }); } }, rowClassNameFun({row}){ if(row.isSelect=='half'){ return "indeterminate"; } }, handleSelectionChange(selection) { let ids = [] let waybill=[] selection.forEach(node => { if(node.isSelect==true){//如果上来勾选了 if(node.children && node.children.length > 0){//判断是否有子元素,如果有子,遍历子 node.children.forEach(child=>{ if(child.isSelect){ let index = ids.findIndex(item => item.outOrderNo === child.outOrderNo && item.packageNo === child.packageNo ); if(index === -1){ ids.push({ outOrderNo: child.outOrderNo, packageNo: child.packageNo }) } if (!waybill.includes(child.trackNumber)) { waybill.push(child.trackNumber); } } }) }else {//如果没有子, console.log('选中') let index = ids.findIndex(item => item.outOrderNo === node.outOrderNo && item.packageNo === node.packageNo ); if(index===-1){ ids.push({ outOrderNo: node.outOrderNo, packageNo: node.packageNo }) } if (!waybill.includes(node.trackNumber)) { waybill.push(node.trackNumber); } } }else if(node.isSelect=="half"){//如果是半选,遍历子,将勾选的子进行push console.log('半选') if(node.children && node.children.length > 0){ node.children.forEach(child=>{ if(child.isSelect){ } }) }else { } }else { console.log('取消') } }) this.waybill=waybill this.ids = ids this.single = this.ids.length !== 1; this.multiple = !this.ids.length }, }, };

这个里面需要有个注意的地方,当父里面有两个子,勾选父,@selection-change="handleSelectionChange"的handleSelectionChange会跑三遍,一遍父、一边父与子、一边子

// 多选框选中数据 handleSelectionChange(selection) { console.log(selection,'selection') }

这个里面还是比较混乱的,打印出来三次,这个我是可以理解的,因为勾选了三个,但是打印的这个顺序,我不太懂,由于有个勾选之后,操作批量下载和批量取消,不勾选的时候,是禁止点击批量下载和批量取消的

效果图

原来代码逻辑

// 多选框选中数据 handleSelectionChange(selection) { console.log(selection,'selection') this.single = selection.length !== 1; this.multiple = !selection.length this.ids = selection.map((item) => item.trackNumber); },

 按理说,这个就能实现以上的功能,但是,没有实现,我进行取消勾选,还是打印了三次,最后一次有值,所以以上代码不能实现此功能

 于是我就对上面的代码进行了改进

// 多选框选中数据 handleSelectionChange: _.debounce(function(selection) { let ids = [] let waybill=[] selection.forEach(node => { console.log(node.isSelect,node) if(node.isSelect==true){//如果上来勾选了 if(node.children && node.children.length > 0){//判断是否有子元素,如果有子,遍历子 node.children.forEach(child=>{ if(child.isSelect){ let index = ids.findIndex(item => item.outOrderNo === child.outOrderNo && item.packageNo === child.packageNo ); if(index === -1){ ids.push({ outOrderNo: child.outOrderNo, packageNo: child.packageNo }) } if (!waybill.includes(child.trackNumber)) { waybill.push(child.trackNumber); } } }) }else {//如果没有子, let index = ids.findIndex(item => item.outOrderNo === node.outOrderNo && item.packageNo === node.packageNo ); if(index===-1){ ids.push({ outOrderNo: node.outOrderNo, packageNo: node.packageNo }) } if (!waybill.includes(node.trackNumber)) { waybill.push(node.trackNumber); } } }else if(node.isSelect=="half"){//如果是半选,遍历子,将勾选的子进行push if(node.children && node.children.length > 0){ node.children.forEach(child=>{ if(child.isSelect){ } }) }else { } }else { } }) this.waybill=waybill this.ids = ids this.single = this.ids.length !== 1; this.multiple = !this.ids.length }, 300),

根据上面取到的this.ids、this.waybill,来进行批量取消操作,可根据自己的代码逻辑进行修改

//取消(取消里面改动点:父packageNo为空,子packageNo有值,后端根据packageNo来进行父与子取消区分) handleCancal(row) { //操作里面的取消 let trackNumber //批量取消 let trackNumbers let outOrderNo let outOrderNos if (row.trackNumber) { trackNumber = row.trackNumber.split(',') outOrderNo = [{ outOrderNo:row.outOrderNo, packageNo:row.packageNo, }] } else { trackNumbers = this.waybill outOrderNos=this.ids } //处理单独取消的弹框换行 let arry let newData = [] for (let index in trackNumber) { newData.push(trackNumber[index] + "") } arry = newData.join('') //处理批量取消的弹框换行 let arrys let newDatas = [] for (let index in trackNumbers) { newDatas.push(trackNumbers[index] + "") } arrys = newDatas.join('') let parmas = outOrderNo || outOrderNos this.$confirm( this.$t('order.surecan') + "" + (arry || arrys) + this.$t('order.waybill') + "" + this.$t('order.notee'), { confirmButtonText: this.$t('operation.confirm'), cancelButtonText: this.$t('operation.cancel'), type: "warning", dangerouslyUseHTMLString: true, }) .then(function () { return cancalOrder(parmas); }) .then(() => { this.getList(); this.msgSuccess(this.$t('msg.application')); }) .catch(function () { }); },

3.CSS

半选的样式

  

/deep/.indeterminate { .el-table-column--selection .cell .el-checkbox { display: block !important; } .el-checkbox__input .el-checkbox__inner { background-color: #4a97eb !important; border-color: #4a97eb !important; color: #fff !important; } } /deep/.indeterminate .el-checkbox__input.is-checked .el-checkbox__inner::after { transform: scale(0.5); } /deep/.indeterminate .el-checkbox__input .el-checkbox__inner::after { border-color: #c0c4cc !important; background-color: #c0c4cc; } /deep/.indeterminate .el-checkbox__input .el-checkbox__inner::after { content: ""; position: absolute; display: block; background-color: #fff; height: 2px; transform: scale(0.5); left: 0; right: 0; top: 5px; width: auto !important; }

 以上就可以实现树状表格选择父节点子节点全选,子节点不全选父节点半选,但是对于handleSelectionChange,里面处理数据还是很懵的,虽然解决了,但是感觉不是最优的方法,如果有好的解决方法,可以分享下,欢迎分享和指正。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3