ElementUI Tree结构如何实现单选以及实现原理

如何实现单选

        在开发中,我们经常会遇到 Tree 树形控件要求单选的这个需求,但是element ui 提供的Tree默认是多选的,要想实现单选,我们就要另外操作一波。

    //  树形结构代码
    <el-tree
        ref="treeRef"
        :data="deptTree"
        show-checkbox
        check-strictly
        node-key="id"
        v-model="selectedKey"
        @check-change="handleNodeClick"
      >
      </el-tree>
data(){
    return{
        selectedKey: null, // 当前选中节点的key
    }
}
method:{
    async handleNodeClick(data, checked) {
      if (checked) {
        this.selectedKey = data.id; // 更新v-model绑定的变量
        this.$refs.treeRef.setCheckedKeys([data.id]); // 只选中当前点击的节点
        console.log(1111);
      }
      

      // data 是当前节点的数据对象
      console.log("当前节点 ID:", data.id); // 输出当前节点的 ID
    },
}

        在上面这段代码中,我们给树形结构设置了ref和node-key,同时也设置了check-strictly

        check-strictly是为了关闭父子之间相互关联,若不关闭,那么当我们勾选子组件的时候,父组件也会自动被勾选上去,从而变成了多选,这明显是不符合需求的。

单选原理

        然后我们给它绑定check-change点击事件handleNodeClick,它需要传递三个参数,我们只需要传递前面两个参数即可

        在我们上面给出的handleNodeClick中,它会在节点选中状态发生变化时才会调用里面的回调函数,上面提及单选实现的原理其实就是就是执行两次这个回调函数,一次是勾选这次所选勾选的,一次是取消上次已经勾选的,所有我们在控制台中会看到输出了两次 “当前节点  ID :X”,9很明显是我们第一次勾选的, 而5才是我们第二次勾选的。

        那么问题来了,这个handleNodeClick为什么调用了两次?它怎么就实现了单选呢?

        原理其实就是在第一次调用handleNodeClick的时候,已经进入到了 if 判断中,那么它会在里面做一件事,就是通过setCheckedKeys去设置目前勾选的节点 ,它通过setCheckedKeys将勾选的节点设置为 ID:5之后,会再次触发handleNodeClick的回调函数(因为通过setCheckedKeys改变了勾选节点)。但是这次触发的节点的ID 为 9 的,这次的9已经不再是勾选状态,所以无法进入if 判断,从而直接输出了 “当前节点  ID :9”

        

单选Tree表单校验

        这里又有新需求了,就是要对单选的Tree进行表单校验,废话不多说,直接上一套rule,

//rules        
     deptIds: [

          {

            required: true,

            type: "array",

            validator: this.validateDeptIds,

            trigger: "change",

          },

        ],
    //自定义校验规则
    validateDeptIds(rule, value, callback) {
      console.log("触发校验");
      console.log(this.selectedKey, "22222");
      if (this.selectedKey?.length === 0) {
        console.log(333);
        callback(new Error("请选择部门"));
      } else {
        callback(); // 校验通过
      }
    },

        这里别问我为啥要自定义规则,可能是我前面的代码设置有问题,在自定义校验规则的函数中拿到的value一直都是undefined/(ㄒoㄒ)/~~。

我们先直接上代码,后面再说问题以及如何解决

    //点击勾选框
    async handleNodeChangePlus(data, checked) {
      console.log(data, checked, "data");
      if (checked) {
       this.selectedKey = [data.id]; // 更新v-model绑定的变量
        this.$refs.tree.setCheckedKeys([data.id]); // 只选中当前点击的节点
        this.$refs.tree.setCurrentKey(data.id); // 设置勾选结点为高亮状态
      } else {
        this.$refs.tree.setCurrentKey("");
        console.log("点击勾选框", this.selectedKey);
        if (data.id === this.selectedKey?.[0]) {
          this.selectedKey = [];
          console.log("取消勾选");
        }
      }
      console.log(this.selectedKey, "deptIds");
    },

单选表单校验流程解析

看到上面的朋友们都知道:从A选择B的流程其实是将B的勾选状态设置为true,然后再次触发将A的勾选状态设置为fasle。这次是真的裂开,这也意味着我们的校验规则会触发两次。从控制台中就可以明显的看到,先将B设置为了true,触发了一次校验,再将A设置为false,同时又触发校验。再我们以前的代码中(上面),并没有对checked为false进行处理,所以我们要对我们的代码升级一波(这里已经是升级版本了哈),对checked为false的进行处理

此外我们要考虑到两个问题:

        ①:Tree一开始没有选择的时候,是直接就将A的勾选设置为true,

        ②:Tree开始有选择的时候,取消勾选,是直接就将A的勾选设置为false,

其实单选规则校验的关键就是在勾选框设置为false的时候去判断,去判断设置false这组data的id是不是就是this.seletedKey里面的id,如果是的话,那么就是上面的第②个问题,取消当前勾选的,那么就要设置seletedKey为空从而触发校验。如果不一样的话,那么就是单纯的从A到B从而触发勾选框的false,这种情况下就无需进行处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值