带复选框的树结构【含indeterminate 属性】---类element树节点
前提:
使用了element中折叠面板组件
indeterminate 属性用以表示 checkbox 的不确定状态element中checkbox组件
和element树节点一样的效果,但是通过修改样式发现太难修改了,只能自己写JS代码了。
因为优化了代码,所以想记录一下~~~各位看官有什么更好的方法可以留言告诉我啊!!!
样式不重要,主要是树形结构的思路~~苦苦百度无果
功能介绍
子级选中时,祖先层级是选中状态或者不确定状态
父级选中时,子级全都选中
思路分析
点击哪个复选框,需要注意将自身的indeterminate修改为false,因为当indeterminate为真时候选中了复选框样式也不会修改
父级的状态直接影响子级,即子级的状态和父级的一样。需要遍历子级的数据,逐个修改
影响祖先层级的状态,需要遍历全部数据,如果第三层级全为真,则第二层级表示为全选,依次类推,如果第二层全选中,则第一层级为全选
效果图
选中一部分:全部选中:
(树形)数据结构
check:表示当前复选框的选中状态
indeterminate:表示当前复选的不确定状态,即一条横
title:该复选框的中文名
child:该复选框的子元素
name:折叠面板的标识符
treeData: {
check: false,
indeterminate: false,
title: '选择所有权限',
child: [
{
title: '舱单管理',
check: false,
indeterminate: false,
name: 'manifestManage',
child: [
{
title: '预配舱单录入',
check: false,
indeterminate: false,
child: [{ title: '录入预配舱单', check: false }],
},
{
title: '预配舱单管理',
check: false,
indeterminate: false,
child: [
{ title: '查询预配舱单', check: false },
{ title: '录入预配舱单', check: false },
{ title: '查看预配舱单', check: false },
{ title: '修改预配舱单', check: false },
{ title: '删除预配舱单', check: false },
{ title: '复制预配舱单', check: false },
{ title: '置为新单', check: false },
{ title: '发送船代', check: false },
{ title: '生成总单', check: false },
{ title: '打印', check: false },
{ title: '下载', check: false },
{ title: '批量打印', check: false },
],
},
],
},
{
title: '舱单管理11',
check: false,
indeterminate: false,
name: 'manifestManage',
child: [
{
title: '预配舱单录入',
check: false,
indeterminate: false,
child: [{ title: '录入预配舱单', check: false }],
},
{
title: '预配舱单管理',
check: false,
indeterminate: false,
child: [
{ title: '查询预配舱单', check: false },
{ title: '录入预配舱单', check: false },
{ title: '查看预配舱单', check: false },
{ title: '修改预配舱单', check: false },
{ title: '删除预配舱单', check: false },
{ title: '复制预配舱单', check: false },
{ title: '置为新单', check: false },
{ title: '发送船代', check: false },
{ title: '生成总单', check: false },
{ title: '打印', check: false },
{ title: '下载', check: false },
{ title: '批量打印', check: false },
],
},
],
},
],
},
HTML部分
- 注意调用函数的时候复选框在第几层就传几个参数,都是传当前索引的值,只有总的复选框比较特殊~不传值change函数有默认参数,只好传个-1
- 使用了element的折叠面板,遍历第一层数据,也就是第一层数据有几个就有几个折叠面板。自定义面板标题,写入第一层数据的title和复选框相关数据
- 每一row左边的第二层数据,右边是第三层数据,如图
-
<el-row style="margin: 10px"> <el-checkbox v-model="treeData.check" :indeterminate="treeData.indeterminate" @change="handleTreeData(-1)" > {{ treeData.title }} </el-checkbox> </el-row> <el-collapse v-for="(item, index) in treeData.child" :key="index" style="margin-bottom: 20px" > <el-collapse-item :name="item.name"> <template slot="title"> <el-checkbox v-model="item.check" :indeterminate="item.indeterminate" @change="handleTreeData(index)" > {{ item.title }} </el-checkbox> </template> <div class="page-row" v-for="(pageitem, pageindex) in item.child" :key="pageindex" > <div class="page-left"> <el-checkbox v-model="pageitem.check" :indeterminate="pageitem.indeterminate" @change="handleTreeData(index, pageindex)" > {{ pageitem.title }} </el-checkbox> </div> <div class="page-right"> <el-checkbox v-for="(poweritem, powerindex) in pageitem.child" :key="powerindex" v-model="poweritem.check" @change="handleTreeData(index, pageindex, powerindex)" style="width: 12%; padding: 2px" > {{ poweritem.title }} </el-checkbox> </div> </div> </el-collapse-item> </el-collapse>
JavaScript部分
【重复唠叨】注意调用函数的时候复选框在第几层就传几个参数,都是传当前索引的值,只有总的复选框比较特殊~不传值change函数有默认参数,只好传个-1
根据分析,修正祖先级和改变子级都要遍历数据,直接每次掉用都遍历数据~
一开始遍历数据的时候使用的数组的filter,返回check值为true的值,但是这样无法判断复选框的不确定状态,所以更换成forEach
先改变子级的数据
handleTreeData(first, second, third) {
this.treeData.child.forEach((v, i) => {
if (first == -1 ) { //最高级~~
v.indeterminate = false
v.check = this.treeData.check
}
v.child.forEach((val, idx) => {
if (first !== undefined && second == undefined) { //第一层
val.check = v.check
}
val.child.forEach((value) => {
if (third == undefined) { //第二层,第三季
value.check = val.check
}
})
})
})
},
需要注意:判断全选还是选中需要先计算子级的全选和不确定状态的数量
计算全选数量,判断子级的全选是否为真,是则+1
计算不确定数量,判断子级的不确定状态或全选状态是否为真,是则+1
vCheckArr = val.check ? vCheckArr+1 : vCheckArr
vIndeterminateArr = val.indeterminate || val.check ? vIndeterminateArr+1 : vIndeterminateArr
判断是否全选,只需判断全选数量是否等于其child的长度
判断是否为不确定状态,判断不确定数量大于0且全选状态不为真
v.check = vCheckArr == v.child.length ? true : false
v.indeterminate = vIndeterminateArr > 0 && !v.check? true: false
~全部代码~
handleTreeData(first, second, third) {
//修改自身的选中indeterminate为false
//必须先修改子级数据
//再影响父级,遍历treeData
let checkArr = 0
let indeterminateArr = 0
this.treeData.child.forEach((v, i) => {
if (first == -1 ) {
v.indeterminate = false
v.check = this.treeData.check
}
let vCheckArr = 0
let vIndeterminateArr = 0
v.child.forEach((val, idx) => {
if (first !== undefined && second == undefined) {
val.check = v.check
}
let valCheckArr = 0
val.child.forEach((value) => {
if (third == undefined) {
value.check = val.check
}
valCheckArr = value.check ? valCheckArr+1 : valCheckArr
})
//判断全选还是不确定
val.check = valCheckArr == val.child.length ? true:false
val.indeterminate = valCheckArr > 0 && valCheckArr<val.child.length? true:false
//计算全选和不确定的数量
vCheckArr = val.check ? vCheckArr+1 : vCheckArr
vIndeterminateArr = val.indeterminate || val.check ? vIndeterminateArr+1 : vIndeterminateArr
})
v.check = vCheckArr == v.child.length ? true : false
v.indeterminate = vIndeterminateArr > 0 && !v.check? true: false
checkArr = v.check ? checkArr+1 : checkArr
indeterminateArr = v.indeterminate || v.check ? indeterminateArr+1 : indeterminateArr
})
this.treeData.check = checkArr == this.treeData.child.length ? true : false
this.treeData.indeterminate = indeterminateArr > 0 && !this.treeData.check? true: false
},