【el-tree 应用】

本文介绍了一种在el-tree组件中实现自定义级联操作的方法,包括如何取消默认的父子节点关联、设置部分节点不可选中及实现子节点选中状态变化不影响父节点等关键功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

el-tree 自定义父子节点级联操作

需求说明

  • 勾选、取消父节点,子节点的状态需跟随改变
  • 勾选、取消子节点,父节点的状态保持不变
  • 设置某些节点不可编辑

起因

el-tree 官网默认的效果无法满足该需求,父子节点存在关联性,选中与取消都会影响各自选中状态。在网上搜了挺多做法但都不起作用/不符预期效果,所以就自己从头写了一下

思路

  • 首先要取消父子节点默认的关联选中,也就是每个节点在选中的时候,都不会去影响其他的节点选中状态,让 每个节点都成为“独立”的个体,通过 check-strictly 属性即可实现
  • 父节点选中取消,所有子节点也要跟着改变;而子节点选中取消却不影响父节点状态,那也就是说我们只需要考虑:当选中某个节点时,如果他存在子节点,就** 递归对他所有的子节点重新设置选中状态**
  • 设置部分节点不可选中?主要是通过 node.disabled = true 来实现,我们只需要从后台获取一下需要特殊处理的节点id值(这里我讲id作为了 el-tree 的key 值)存储在一个数组中(specialNodeList),在初始化的时候遍历 el-tree 的 data ,将 key/id 值存在 specialNodeList 中的 节点设置 disabled = true 即可

具体

  • 第一步
    为了使父子节点不互相影响,第一步最关键的是给 el-tree 设置 :check-strictly=“true” 属性
    在这里插入图片描述

  • 第二步
    使用 el-tree 的 check-change 响应事件,每次节点选中状态改变时
    (网上还有很多使用 node-click、check 事件来实现的,这里看个人)

1.获取当前 el-tree 选中的所有节点信息 (数组保存 - this.categoryList)

this.categoryList = this.$refs.tree.getCheckedKeys()

2.获取当前节点的所有子节点 key (需要过滤掉那些不可选中的节点 key - 按需要来)

let childIds = []
// 整理并过滤掉特殊的子节点 id 数据 / key 值
this.getChildrenId(data,childIds)
    getChildrenId(data,childIds){
      if (data.children && data.children.length){
        data.children.forEach(item=>{
          if (this.specialNodeList.indexOf(item.id) === -1){
            // 不是特殊节点,才递归获取
            childIds.push(item.id)
            if (item.children){
              this.getChildrenId(item,childIds)
            }
          }
        })
      }
    },

3.通过 check-change 事件的第二个参数(共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点),来判断当前节点是选中还是取消选中
4.如果是选中,就把当前节点的所有子节点 key 加入 this.categoryList,并去重,重新赋值当前 el-tree 选中节点 key

if (checked){
        //选中父节点,把所有子节点加入到 this.categoryList 中,并去重
        const arr = this.categoryList.concat(childIds)
        this.categoryList = [...new Set(arr)]
        // 重新赋值选中节点
        this.$refs.tree.setCheckedKeys(this.categoryList)
      } 

5.如果是取消选中,把所有子节点 key 从 this.categoryList 中删除,重新赋值当前 el-tree 选中节点 key

else {
        // 取消选中父节点,把所有子节点从 this.categoryList 中去除
        childIds.forEach(item=>{
          let index = this.categoryList.indexOf(item)
          if (index !== -1){
            // 选中的节点数组中包含该子节点,将其去除
            this.categoryList.splice(index,1)
          }
        })
        // 重新赋值选中节点
        this.$refs.tree.setCheckedKeys(this.categoryList)
      }

6.补充一下回显效果逻辑
每次打开的时候,由于要回显勾中我们本来就关联的节点,这些节点会隐式的调用handleCheck 响应方法,会引起什么情况?
会引起每个节点都自动把自己的子节点都勾选上了,导致脏数据(多勾选了一些子节点),而且是默认要选中多少个节点,就自动调用多少次响应方法
补上以下代码

//自定义一下 backTime 全局变量
//且每次初始化时都赋值一下 this.backTime = 1
if (this.backTime <= this.defaultList.length){
        this.backTime ++;
        return;
      }

代码

el-tree 定义

<el-tree
            ref="tree"
            :data="data"
            show-checkbox
            node-key="id"
            default-expand-all
            @check-change="handleCheck"
            :default-checked-keys="defaultList"
            :check-strictly="true"
          >

check-change 事件

    /**
     * 父节点选中状态变化,子节点跟随
     * 子节点选中状态变化,父节点不变
     * 核心:通过改变当前选中节点信息 this.categoryList 数组中的元素
     *      再使用 setCheckedKeys 函数重新赋值选中节点
     * @param data
     * @param checked
     */
    handleCheck(data,checked){
    
	  // 这里默认需要选中几个节点,就会调用多少次,达到次数才执行父子节点关联逻辑->才生效自动选中子节点
      if (this.backTime <= this.defaultList.length){
        this.backTime ++;
        return;
      }


      this.categoryList = this.$refs.tree.getCheckedKeys()
      let childIds = []
      // 整理并过滤掉特殊的子节点 id 数据 / key 值
      this.getChildrenId(data,childIds)

      if (checked){
        //选中父节点,把所有子节点加入到 this.categoryList 中,并去重
        const arr = this.categoryList.concat(childIds)
        this.categoryList = [...new Set(arr)]
        // 重新赋值选中节点
        this.$refs.tree.setCheckedKeys(this.categoryList)
      } else {
        // 取消选中父节点,把所有子节点从 this.categoryList 中去除
        childIds.forEach(item=>{
          let index = this.categoryList.indexOf(item)
          if (index !== -1){
            // 选中的节点数组中包含该子节点,将其去除
            this.categoryList.splice(index,1)
          }
        })
        // 重新赋值选中节点
        this.$refs.tree.setCheckedKeys(this.categoryList)
      }
    },


	/**
	*
     * @param data  当前节点
     * @param childIds  保存选中节点的所有子节点 key
	*/
    getChildrenId(data,childIds){
      if (data.children && data.children.length){
        data.children.forEach(item=>{
        // this.specialNodeList 为特殊不可选中的节点 key 集合,看个人需要可去掉此处判断代码
          if (this.specialNodeList.indexOf(item.id) === -1){
            // 不是特殊节点,才递归获取
            childIds.push(item.id)
            if (item.children){
              this.getChildrenId(item,childIds)
            }
          }
        })
      }
    },

ps:el-tree 不同响应事件里面,data 跟 node 不是同一个东西… … 所以还是根据自己的需要选择正确的 event 吧。。本实现方式仅达到了实现效果的程度,还有很多更好的方法可以实现,仅记录==

也可以参考这篇文章:el-tree 带效果图
本文实现的效果,仅仅是比此文多了一个:取消子节点选中状态,不取消父节点的选中状态 ==

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值