开发需求15-使用el-checkbox组件实现el-tree组件的父子关联关系(非全选/全不选)

需求描述:

大家都知道el-tree可以很明显的通过选中来体现上下节点的父子选中状态,那么如果要求把后端把el-tree的数据结构,通过一个展开的list返回给你,使用el-checkbox组件渲染每一个节点,同时要求选中某一个节点,同时可以选中其父节点和子节点;取消也是一样。

思路:

首先el-checkbox是没有el-tree的check-strictly来严格遵循父子相关联的属性,那么想实现就需要

1. 向下递归查询点击节点的子节点。

2. 向上递归查询点击节点的父节点。

3. 通过indeterminate 属性用以表示 checkbox 的不确定状态,用来表示父节点的选中效果

实现效果:

使用el-checkbox实现el-tree父子关系选中效果

代码实现:

html部分:

<template>
  <div>
      <el-checkbox
        v-for="(item, key) in labelList"
        :label="item.labelName"
        :key="key"
        v-model="item.checked"
        :indeterminate="item.isIndeterminate"
        @change="changeCheck(item)"
      ></el-checkbox>
  </div>
</template>

JavaScript部分:

<script>
export default {
  data() {
    return {
      listQuery: {
        labelValue: [],
      },
      labelList: [
        // {
        //     labelName: '根目录',
        //     id: 1,
        //     parentId: -1,
        //     checked: false
        // },
        {
          labelName: '一级 1',
          id: 2,
          parentId: 1,
          checked: false,
        },
        {
          labelName: '一级 2',
          id: 3,
          parentId: 1,
          checked: false,
        },
        {
          labelName: '一级 3',
          id: 4,
          parentId: 1,
          checked: false,
        },
        {
          labelName: '二级 1-1',
          id: 5,
          parentId: 2,
          checked: false,
        },
        {
          labelName: '三级 1-1-1',
          id: 9,
          parentId: 5,
          checked: false,
        },
        {
          labelName: '三级 1-1-2',
          id: 10,
          parentId: 5,
          checked: false,
        },
        {
          labelName: '二级 2-1',
          id: 6,
          parentId: 3,
          checked: false,
        },
        {
          labelName: '二级 2-2',
          id: 7,
          parentId: 3,
          checked: false,
        },
        {
          labelName: '二级 3-1',
          id: 8,
          parentId: 4,
          checked: false,
        },
        {
          labelName: '二级 3-2',
          id: 11,
          parentId: 4,
          checked: false,
        },
        {
          labelName: '三级 3-2-1',
          id: 12,
          parentId: 11,
          checked: false,
        },
        {
          labelName: '三级 3-2-2',
          id: 13,
          parentId: 11,
          checked: false,
        },
        {
          labelName: '三级 3-2-3',
          id: 14,
          parentId: 11,
          checked: false,
        }
      ]
    }
  },
 methods: {
    changeCheck(row) {
      // 向下选中子级
      this.downRecursiveChildren(row)

      // 每次添加前先清空选中的标签的name数组
      this.listQuery.labelValue = []
      this.labelList.map((i) => {
        if (i.checked) {
          this.listQuery.labelValue.push(i.labelName)
        }
      })
      console.log('a', this.listQuery.labelValue)
    },
    downRecursiveChildren(row, isGrandChildren = false) {
      if (row.isIndeterminate) {
        row.isIndeterminate = false
      }
      this.labelList.forEach((item) => {
        // 判断点击的标签下,是否有子标签,如果有状态设置为true
        if (row.id === item.parentId) {
          item.checked = row.checked
          // 判断点击的标签下的子标签是否还有子级,如果有,递归调用,把所有子级全部选中
          if (this.labelList.some((v) => item.id === v.parentId)) {
            this.downRecursiveChildren(item, true)
          }
        }
      })
      // 如果没有了,return
      if (isGrandChildren) return
      this.upRecursiveParent(row)
    },
    // 向上寻找父级,添加状态
    upRecursiveParent(row) {
      // 获取点击标签的父标签
      let parentNode = this.labelList.find((v) => v.id == row.parentId)
      // 定义点击标签的兄弟数组
      let subing_list = []

      this.labelList.forEach((item) => {
        // 判断点击标签是否有相同的父级,如果有把所有的兄弟标签获取到
        if (item.parentId === row.parentId) {
          subing_list.push(item)
          console.log('2', subing_list)
        }
      })
      if (parentNode) {
        // 所有的兄弟节点全部选中且没有不确定状态, 需要选中父标签节点
        if (
          subing_list.every((item) => item.checked && !item.isIndeterminate)
        ) {
          // 全选中且没有不确定状态
          parentNode.checked = true
          parentNode.isIndeterminate = false
          console.log('3')
        } else if (
          // 所有的兄弟节点全部选中且没有不确定状态, 需要选中父标签节点
          subing_list.every((item) => !item.checked && !item.isIndeterminate)
        ) {
          // 全不选中并且没有不确定状态,不需要选中父标签节点
          parentNode.checked = false
          parentNode.isIndeterminate = false
          console.log('4')
        } else {
          // 有部分选中,父节点需要设置为半选状态
          parentNode.checked = false
          parentNode.isIndeterminate = true
          console.log('5', parentNode)
        }
        if (parentNode.parentId !== 1) {
          this.upRecursiveParent(parentNode)
        }
      }
    }
  },
}
</script>
  • 15
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr_LiuP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值