ElementUI级联选择器点击整行选中前面的单选框或者多选框

360 阅读1分钟
需求:产品要求级联选择器以hover的形式展开,点击label的时候选中前面的单选框或者多选框

html代码:

1.png

第一次实现方案:利用css实现。

原理是: 把checkbox的元素层级放到最顶层,点击label的时候其实是点击到了checkbox框。

缺点: 且tooltip会收影响,因为checkbox是在最顶层了,所以鼠标上移的时候hover到的元素不是label了,就不会出现tooltip悬浮框了

核心代码:

<style>
  /*cascader选中label的时候勾选前面的多选框*/
  .project-cascader .el-cascader-menu .el-checkbox {
    width: 100%;
    height: 100%;
    z-index: 10;
    position: absolute;
  }
  .project-cascader .el-cascader-menu .el-cascader-node__label {
    margin-left: 10px;
  }
</style>

第二种方案:利用previousElementSibling

原理: 利用previousElementSibling拿到当前点击元素的前一个元素(也就是checkbox)然后给checkbox或radio添加点击事件

缺点: 使用setInterval会消耗性能,代码不优雅。

data() {
    return {
        dateTimer =  0;
    }
}

beforeDestroy() {
  clearInterval(this.dateTimer); // 关闭定时器
}

startTimer() {
  // cascader开启多选模式下,选中label时候也能勾选前面的多选框
  clearInterval(this.dateTimer);
  this.dateTimer = setInterval(() => {
    document.querySelectorAll('.t-el-cascader-node__label').forEach((el: any) => {
      el.onclick = function () {
        if (this.previousElementSibling) this.previousElementSibling.click();
      };
    });
  }, 500);
}

第三种方案:利用previousElementSibling,是对第二种方案的优化,不使用定时器,利用点击事件去优化

看一下浏览器渲染的dom结构: 我这里是使用公司自己的组件库所以会加上前缀“t-”。

核心代码如下:

3.png

2.png

// 点击label选中前面的单选框或多选框
this.$nextTick(() => {
    let d = document.getElementsByClassName('project-cascader');
    for (const ele of d) {
        if (ele && !(ele as any).onclick) {
          (ele as any).onclick = function (e: any) {
            if (e.target.parentNode.className === 't-el-cascader-node__label') { // 这里要自己改成对应的el-cascader-node__label
              e.target.parentNode.previousElementSibling.click();
            }
          };
        }
    }
});