带复选框的树结构【含indeterminate 属性】---类element树节点

发布于 2021-7-21 15:27
浏览
0收藏

前提:


使用了element中折叠面板组件
indeterminate 属性用以表示 checkbox 的不确定状态element中checkbox组件
和element树节点一样的效果,但是通过修改样式发现太难修改了,只能自己写JS代码了。
因为优化了代码,所以想记录一下~~~各位看官有什么更好的方法可以留言告诉我啊!!!
样式不重要,主要是树形结构的思路~~苦苦百度无果


功能介绍


子级选中时,祖先层级是选中状态或者不确定状态
父级选中时,子级全都选中


思路分析


点击哪个复选框,需要注意将自身的indeterminate修改为false,因为当indeterminate为真时候选中了复选框样式也不会修改
父级的状态直接影响子级,即子级的状态和父级的一样。需要遍历子级的数据,逐个修改
影响祖先层级的状态,需要遍历全部数据,如果第三层级全为真,则第二层级表示为全选,依次类推,如果第二层全选中,则第一层级为全选

效果图


选中一部分:带复选框的树结构【含indeterminate 属性】---类element树节点-开源基础软件社区全部选中:带复选框的树结构【含indeterminate 属性】---类element树节点-开源基础软件社区

 

(树形)数据结构


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左边的第二层数据,右边是第三层数据,如图带复选框的树结构【含indeterminate 属性】---类element树节点-开源基础软件社区
  • 带复选框的树结构【含indeterminate 属性】---类element树节点-开源基础软件社区
        <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
    },

 

标签
已于2021-7-21 15:27:38修改
收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐