关于前端:带复选框的树结构含indeterminate-属性类element树节点

37次阅读

共计 4872 个字符,预计需要花费 13 分钟才能阅读完成。

前提:

  • 应用了 element 中折叠面板组件
  • indeterminate 属性用以示意 checkbox 的不确定状态 element 中 checkbox 组件
  • 和 element 树节点一样的成果,然而通过批改款式发现太难批改了,只能本人写 JS 代码了。
  • 因为优化了代码,所以想记录一下~~~ 各位看官有什么更好的办法能够留言通知我啊!!!
  • 款式不重要,次要是树形构造的思路~~ 苦苦百度无果

性能介绍

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

思路剖析

  1. 点击哪个复选框,须要留神将本身的 indeterminate 批改为 false,因为当 indeterminate 为真时候选中了复选框款式也不会批改
  2. 父级的状态间接影响子级,即子级的状态和父级的一样。须要遍历子级的数据,一一批改
  3. 影响先人层级的状态,须要遍历全副数据,如果第三层级全为真,则第二层级示意为全选,顺次类推,如果第二层全选中,则第一层级为全选

效果图

选中一部分:

全副选中:

(树形)数据结构

  • 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
    },

正文完
 0