element tree 设置check-strictly=true后,手动重写逻辑实现父子关联

发布于:2024-07-01 ⋅ 阅读:(51) ⋅ 点赞:(0)

前言

遇到需求如下:

  • 当取消勾选某个节点为按钮时,并且该节点的同级节点都为按钮时(此时父级是勾选状态),不管同级节点是否都取消勾选,那么父级不取消勾选。除非手动取消父级勾选(原因是:页面和按钮不构成联动逻辑
  • 当同级节点为按钮和菜单混合,或者都为菜单时,并且同级都取消勾选了,那么父级勾选。

综上,想了下,打算设置element tree 父子不关联,然后手动重写关联逻辑。

代码

<template>
  <div>
    <el-tree :data="treeData" node-key="id" :props="defaultProps" @check="handleCurrCheck"
      :check-strictly="checkStrictly" ref="treeRef" default-expand-all show-checkbox>
    </el-tree>
    <el-button type="primary" style="margin-top: 20px;" @click="handleTreeChecked">获取当前选中数据</el-button>
  </div>
</template>


<script>
/**
 * 设置父子不关联。根据业务需求手动重写父子关联逻辑
 * type: 1 为按钮 0 为菜单
 */
export default {
  data() {
    return {
      treeData: [
        {
          id: 1,
          label: '一级 1',
          children: [
            {
              id: 4,
              label: '二级 1-1',
              parentId: 1,
              children: [
                {
                  id: 7,
                  label: '三级 1-1-1',
                  parentId: 4
                },
                {
                  id: 8,
                  label: '三级 1-1-2',
                  parentId: 4
                }
              ]
            }
          ]
        },
        {
          id: 2,
          label: '一级 2',
          children: [
            {
              id: 5,
              label: '按钮 2-1',
              type: 1,
              parentId: 2
            }
          ]
        },
        {
          id: 3,
          label: '一级 3',
          children: [
            {
              id: 6,
              label: '按钮 3-1',
              type: 1,
              parentId: 3
            },
            {
              id: 9,
              label: '二级 3-2',
              type: 0,
              parentId: 3
            }
          ]
        }
      ],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      checkStrictly: true,
    };
  },
  methods: {
    handleCurrCheck(data) {
      let currentNode = this.$refs.treeRef.getNode(data)
      if (currentNode.checked) { // 选中
        this.recursionParentChecked(currentNode.parent, true) // 该级以上,父级选中
        this.recursionChildChecked(currentNode.childNodes, true) // 该级以下,子级全部选中
      } else { // 取消
        this.recursionChildChecked(currentNode.childNodes, false)// 该级以下,子级全部取消
        // if (data.type != 1) { // 是菜单,父级就正常取消
        this.recursionParentChecked(currentNode.parent, false, data.type) // 该级以上,父级需要判断
        // }
      }
    },
    recursionParentChecked(node, isChecked, type) { // 递归父级
      if (node.level != 0) {
        if (isChecked) { // 勾选
          if (node) {
            this.$refs.treeRef.setChecked(node.data, true)
            this.recursionParentChecked(node.parent, isChecked)
          }
        } else { // 取消勾选
          if (node && node.childNodes) {
            const res = node.childNodes.filter(item => !item.checked)
            const isExistMenu = node.childNodes.some(item => !item.data.type)
            if (node.childNodes.length == res.length && isExistMenu) { // 子级全部取消了,并且没有菜单,则父级取消勾选状态
              this.$refs.treeRef.setChecked(node.data, false)
            }
            this.recursionParentChecked(node.parent, isChecked, type)
          }
        }
      }
    },
    recursionChildChecked(node = [], isChecked) { // 递归子级
      node.forEach(item => {
        this.$refs.treeRef.setChecked(item.data, isChecked)
        this.recursionChildChecked(item.childNodes, isChecked)
      })
    },
    handleTreeChecked() {
      const res = this.$refs.treeRef.getCheckedKeys()
      console.log(res);
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>