el-tree取消特定叶子节点与上级的勾选联动

在vue.js中使用el-tree时,文章介绍了如何在菜单和按钮的权限选择场景下,实现特定按钮与上级菜单不遵循强制父子联动关系。通过设置`check-strictly="true"`并自定义函数来处理节点的checked状态,从而达到预期效果。重点在于unlinkNode函数,用于解除特定类型节点(如type为'button')与上级的联动。

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

      如果你用el-tree做菜单和按钮的权限数据选择,那么按钮和他所属的菜单联动关系之一是当前菜单可以独立选择,即不选按钮可单独选择菜单。

      那么问题来了,el-tree的联动模式只有是否强制遵循父子联动关系,并没有为单独的特例而破格。在菜单和按钮权限的大背景之下,我们需要的是按钮和他的上级菜单不遵循强制的父子联动关系,而其余菜单则强制遵循父子联动关系。明白了这一点之后,我们需要对el-tree做一下简单的封装,写上几个函数帮助我们完成代办的事项。

      下面是最后实现的效果展示

     首先要明确一点el-tree判断一个节点是否被勾选是根据当前节点对象数据中的checked去判断的,checked 为true则判定勾选,false则为未勾选。一个节点对象的数据结构如下所示:

        然后我们把el-tree的联动模式设置为:check-strictly="true" 严格的遵循父子不互相关联,剩下的操作就是我们自己去完成菜单和菜单之间,菜单和按钮之间的联动关系。其中的核心操作就是在合适的时机去设置节点的checked值。

        el-tree二次封装的代码如下:

<template>
  <el-tree
    :data="data"
    show-checkbox
    :node-key="nodeKey"
    :default-checked-keys="defaultCheckedKeys"
    highlight-current
    :check-strictly="true"
    @check="nodeCheck"
    :ref="refKey"
    >
  </el-tree>
</template>
<script>
let count = 0
export default {
  name: 'hb-tree',
  props: {
    'data': {
      type: Array,
      default () { return [] }
    },
    'nodeKey': {
      type: String,
      default: 'id'
    },
    'defaultCheckedKeys': {
      type: Array,
      default () { return [] }
    },
    'unlinkNode': {
      type: Array,
      default () { return ['type', 'button'] }
    },
    'checkedKeyList': {
      type: Array,
      default () { return [] }
    }
  },
  watch: {
    defaultCheckedKeys () {
      this.$emit('update:checkedKeyList', this.defaultCheckedKeys)
    }
  },
  data () {
    return {
      refKey: '',
      treeNode: ''
    }
  },
  methods: {
    setNodes (list = [], flag = false) {
      if (!list.length) return []
      for (let item of list) {
        item.checked = flag
        if (item.childNodes && item.childNodes.length) this.setNodes(item.childNodes, flag)
      }
    },
    getParentKey (node = {}, ret = []) {
      node.key && ret.push(node.key)
      if (node.parent) this.getParentKey(node.parent, ret)
      return ret
    },
    unSelectedMenu (node) {
      if (node.id === 0) return
      let flag = true
      for (let item of node.childNodes) {
        if (item.checked) {
          flag = false
          break
        }
      }
      if (flag) {
        node.checked = false
        this.unSelectedMenu(node.parent)
      }
    },
    nodeCheck (data, obj) {
      let isSelected = obj.checkedKeys.includes(data.id)
      let curNode = this.treeNode.getNode(data.id)
      let nodes = curNode.childNodes || []
      this.setNodes(nodes, isSelected)
      if (isSelected) {
        let keys = this.getParentKey(curNode.parent)
        keys.forEach(item => {
          this.treeNode.setChecked(item, true)
        })
      }
      if (!isSelected && (data[this.unlinkNode[0]] !== this.unlinkNode[1])) this.unSelectedMenu(curNode.parent)
      this.$emit('check', data, obj)
      this.$emit('update:checkedKeyList', this.treeNode.getCheckedKeys())
    },
    getTreeNode () {
      return this.$refs[this.refKey]
    }
  },
  created () {
    this.refKey = this.ref || `tree${count++}`
  },
  mounted () {
    this.treeNode = this.getTreeNode()
  }
}
</script>

         这里解释一下unlinkNode的作用,unlinkNode可以指定需要解除联动关系节点的某个属性和属性值,这会用于后续的判断,这里的默认值是['type', 'button'], 即代表如果节点的type是button,那么取消该节点时将不会和上级发生联动。

         操作函数中对于checked的赋值都是用到了递归,关于树形结构的递归可以参考笔者的另外几篇博客非标准树状结构数据的处理js遍历树形结构方法过滤树形结构数据并获取新的树形结构。这里简单讲一些封装的主要逻辑,当你操作复选框的时候就会进入nodeCheck进行一系列判断的。首先我们要获取当前节点的选中状态(true为被选中,false为未选中),然后根据这个状态去设置他子节点的checked值,接下来如果他处于被选中的状态那么去设置他父级节点的选中状态(这里仅当他父级节点未选中时才会去设置父级节点的checked为true)。如果当前被操作的节点处于未勾选的状态那么会根据unlinkNode去判断是否要进一步的取消上级节点的选中状态。

        关于el-tree取消特定叶子节点与上级的勾选联动的介绍就到此结束了,如有任何疑问可与bolg下方留言。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值