前提:

  • 应用了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 : vCheckArrvIndeterminateArr = val.indeterminate || val.check ? vIndeterminateArr+1 : vIndeterminateArr
    • 判断是否全选,只需判断全选数量是否等于其child的长度
    • 判断是否为不确定状态,判断不确定数量大于0且全选状态不为真

      v.check = vCheckArr == v.child.length ? true : falsev.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    },