shayloyuki

科技是第一生产力

 

el-tree 父子节点勾选框半关联

问题

有个节点带 checkbox 的 el-tree 父子节点需要半关联,即:

1.勾选父节点,子节点不会被勾选;
2.但是勾选子节点,父节点会被勾选。

解决

第一步:实现父子节点不相互关联

子组件:

image

image

父组件:

image

image

第二步:实现勾选子节点,父节点会被勾选

关键问题是如何勾选某个节点

  1. 方式一:setChecked() 通过父节点的 nodeKey 或者 data;
  2. 方式二:找到父节点的 node,设置 checked = true

方式一(推荐):监听每个节点,若被勾选,则勾选它的父节点。即:

通过 check-change 判断:若当前节点被勾选,则勾选它的父节点。

image

image

子组件 MenuTree:

@check-change="(data, checked, indeterminate) => $emit('custom-check-change', {data, checked, indeterminate})"

    // 通过 key / data 设置某个节点的勾选状态 // key/data, checked, deep
    setChecked(key, checked, deep) {
      this.$refs.tree.setChecked(key, checked, deep);
    },

父组件:

@custom-check-change="customCheckChange"

    // 自定义树节点的 check-change 事件
    customCheckChange(argus) {
      const { data, checked } = argus
      // 若当前节点勾选,则也勾选父节点
      if (!data.pid) return
      if (checked) {
	// nodeKey 为 el-tree 的 node-key,默认为 'id'
        const { nodeKey, nodeData, setChecked } = this.$refs['menuTree']
        if (nodeKey === 'id') {
          setChecked(data.pid, true)
        } else {
          // 树形扁平化 // this.extractTree() 为封装的公共方法
          const flatNodeData = this.extractTree(nodeData,'children')
          const target = flatNodeData.find(ele => ele.id == data.pid)
          if (target) {
            setChecked(target[nodeKey], true)
          }
        }
      }
    }

方式二:

分析

查找官方文档发现:el-tree 的 自定义事件的参数中包含 node 且较为合适的只有 node-click 事件。可以通过它找到父节点的 node 并设置checked = true

image

但是有个问题node-click 事件仅在点击节点名称时才会触发,如果是点击复选框,则不会触发。

解决:给节点名称前设置伪元素,伪元素覆盖原来的复选框,点击复选框实际上是点击了伪元素。

代码

子组件

@node-click="handleNodeClick"

image

 /* 功能:点击复选框,相当于点击节点这一行 */
// 节点名 // custom-tree-node 是自定义节点的类名,如果没有自定义节点,则用 el-tree-node__label
::v-deep .custom-tree-node{
    position: relative;
  }

// 节点名前的复选框:伪元素,绝对定位;点击伪元素触发的是主元素的 click 事件
::v-deep .custom-tree-node:before{
  content:'';
  width:20px;
  height: 20px;
  display: block;
  position:absolute;
  top:0px;
  left:-24px;
  z-index:999;
}

// 被伪元素覆盖的原来的复选框
::v-deep .el-checkbox__inner{
  top:0;
}

效果

image

参考链接

  1. vue el-tree树形结构的check-strictly属性

  2. element-ui el-tree选择子节点时同时选择并提交父节点逻辑问题

  3. 浅谈css的伪元素::after和::before && 给伪元素添加点击事件

  4. js伪元素点击事件实现的两种方法

posted on 2022-11-16 12:06  shayloyuki  阅读(1184)  评论(0编辑  收藏  举报

导航