preface
The menu function (permission management) page in the middle and background project is always essential, and the tree form of the El-Table component in Element cannot well meet the corresponding business requirements. Therefore, the idea is to use el-Checkbox to replace the checkbox in the first column of the list, and then control the corresponding check event by the function. What write perhaps is not very perfect, still ask everybody big guy to give advice more!
Achieve results
Without further ado, let’s look at the code!
Page code
<el-table border :data="tableData" row-key="id" default-expand-all @select-all="chooseAll" > <! <el-table-column type="selection" width="55" align="center" fixed="left" > <template slot-scope="{ row }"> <! -- Replace the original checkbox with el-checkbox --> <! --> < el-checkBox V-model ="row.check" : indeTerminate =" row.intype" @change="chooseBlock(row)" ></el-checkbox> </template> </el-table-column> <el-table-column show-overflow-tooltip Prop ="title" label=" menu name "width="180" Fixed ="left" ></el-table-column> <el-table-column label=" function operation "> <template slot-scope="{ row }"> <! <el-checkbox-group v-model="row.actives"> <el-checkbox v-for="item in row.actionList" :key="item.id" :label="item.actionName" @change="chooseActive(row)" >{{ item.title }}</el-checkbox > </el-checkbox-group> </template> </el-table-column> </el-table> </el-card>Copy the code
The data format
Data () {return {tableData: [{title: "menu 1", id: 1, // pid parent id: 0 // ActionList: [{id: 0, actionName: "show", title: [{id: 0, actionName: "show", title: "Show",},], / / selected (in the menu function actives of preservation) : [], / / the lower menu children: [],},],}; },Copy the code
Corresponding event function
methods: {
// 表格全选
chooseAll(val) {
// 需要递归处理数据
if (val.length > 0) {
// 大于0说明是选中状态
this.handleAll(true, this.tableData);
} else {
// 取消全选
this.handleAll(false, this.tableData);
}
},
// 选中/取消所有选项
handleAll(bol, list) {
list.forEach((ele) => {
// checkbox赋值
ele.check = bol;
// 重置部分选中状态
ele.inType = false;
if (ele.children && ele.children.length > 0) {
// 判断children存在且不为空, 则当前对象没有功能选项, 遍历children
this.handleAll(bol, ele.children);
} else {
// 当前对象存在选项
// 清空已选
ele.actives = [];
// bol = true则全选 为false什么都不做
if (bol) {
ele.actionList.forEach((item) => {
ele.actives.push(item.actionName);
});
}
}
});
},
// 左侧选框选中
chooseBlock(obj) {
// 选中时就不存在部分选中了,清除部分选中状态
obj.inType = false;
if (obj.actionList.length > 0) {
// 数组长度大于0, 存在对应的选项, 处理数据
// 清空选中数据
obj.actives = [];
// 判断选中状态 true:全选 false:取消
if (obj.check) {
// 全选 遍历选项列表
obj.actionList.forEach((ele) => {
obj.actives.push(ele.actionName);
});
}
// 更新菜单选中状态
this.inspectRow(obj.pid, this.tableData);
} else {
// 判断children是否为空或不存在
if (obj.children && obj.children.length > 0) {
if (obj.check) {
this.handleAll(true, obj.children);
} else {
this.handleAll(false, obj.children);
}
}
}
},
// 选中功能选项
chooseActive(obj){
// actives.length不为0说明有选中的项
if(obj.actives.length != 0){
if(obj.actives.length < obj.actionList.length){
// 已选数量小于选项数量, 未全选, 菜单选框部分选中
obj.inType = true;
obj.check = false;
} else {
// 已选数量等于选项数量, 全选, 菜单选框选中
obj.inType = false;
obj.check = true;
};
} else {
// actives.length == 0 没有选中, 取消选框状态
obj.check = false;
obj.inType = false;
};
// 更新菜单选中状态
this.inspectRow(obj.pid, this.tableData);
},
// 选中功能选项, 更新菜单行选中状态
inspectRow(pid, list){
// 根据pid遍历数组
if(pid != 0){
// pid不为0 不为一级菜单
// 遍历数组 寻找对应项
let mobj = {};
list.forEach(ele => {
if(ele.id == pid){
// 符合条件, 暂存
mobj = ele;
}
});
if(mobj.id){
// 已找到对应pid的对象
let listNum = mobj.children.length;
let checkNum = 0;
let inTypeNum = 0;
// 遍历数组, 获取已全选和部分选中的对象数量
mobj.children.forEach(ele => {
ele.check == true ? checkNum++ : "";
ele.inType == true ? inTypeNum++ : "";
});
if(checkNum == listNum){
// 已全选数量和数组数量一致, 全选状态
mobj.check = true;
mobj.inType = false;
} else if(checkNum < listNum && checkNum > 0){
// 存在部分子对象全选, 父对象显示部分选中状态
mobj.check = false;
mobj.inType = true;
} else if(inTypeNum > 0){
// 没有全选状态的子对象, 但存在部分选中的子对象
// 父对象显示部分选中状态
mobj.check = false;
mobj.inType = true;
} else {
// 子对象无选中
mobj.check = false;
mobj.inType = false;
};
// pid不为0 代表还有父级对象, 递归改变父级选框状态
if(mobj.pid != 0){
this.inspectRow(mobj.pid, this.tableData);
}
} else {
// 当前数据层未找到符合条件的对象, 寻找下一层
list.forEach(ele => {
if(ele.children && ele.children.length > 0){
this.inspectRow(pid, ele.children);
}
});
}
}
}
},
Copy the code
legacy
As shown in the figure, the selection box in the table header only has the function of controlling full selection/reverse selection, and the corresponding selected state cannot be displayed in the data display. It is not as good as the linkage display of the data part below, which is a slight flaw. If there are better methods or ideas, please give me more advice! (Thanks to you guys)