ant-design-vue中实现a-tree树形控件父子关联选中过滤的算法

在使用ant-design-vue的框架时,a-tree是比较常用的组件,比较适合处理树形结构的数据。

但是在与后台数据进行授权交互时,就不友好了。

在这里插入图片描述
在原生官方文档的例子中,若子项被勾选,则父级节点会被关联勾选,但这勾选并不一定是选中的意思。有可能是半选中,通过方框样式选中,也就是说父级节点的值不会出现在checkedKeys的数组中。

<a-tree
  v-model:checkedKeys="checkedKeys"
  checkable
  :tree-data="treeData"
>
</a-tree>

这对后端数据授权处理是不友好的。因为一般授权子节点时,父级节点必须是也授权的,否则应用无法到达子节点的功能。也就是说,关联被授权的父子节点的ID都要传给后端。

提交的时候,到还好说。将所有选中的列表和半选中的列表合并起来提交就可以了。

const handleCheck = (checkedKeys, e) => {
  const {halfCheckedKeys } = e;
  const allCheckedKeys = [...checkedKeys, ...halfCheckedKeys];
};

但是数据回写的时候就难受了,数据库里的授权列表回写到a-tree组件时,由于父节点被回传过来,那么当父节点被选中时,所有子节点都会被选中,这与实际不符。

所以需要将服务传过来的数据allCheckedKeys处理,再还原成选中checkedKeys和半选中halfCheckedKeys的两部分。

这个业务逻辑比较复杂,需要比较授权列表和树形结构数据。
在这里插入图片描述
我在网上找了很久都没找到关于此业务的算法逻辑。但是找到了另外的两种解决办法:

一是更改数据库结构,添加授权列表的字段分为选中和半选中的状态,传给后端服务时ID分类传输。
二是父子节点不再关联,即添加a-tree的属性为checkStrictly="true",分别独立处理单个节点的逻辑。

第一种方法缺点就是数据表设计不规范,数据库存储了适应前端页面的数据。优点是避免了js编写筛出未全部选中的父级id的工作。

第二种方法缺点是勾选父级节点时,子节点不会被关联勾选,层级很多时,操作不方便。同时子节点勾选时,可能遗漏父节点的勾选。当然可以再写代码,补上往上和往下关联的逻辑。但是还是有缺点,父节点被勾选时,是通过“√”表示,若不展开下级列表,会不知道子节点是否被全选上。

最后思来想去,感觉两种方法都有缺点。我还是觉得自己将这个业务逻辑的算法写出来吧。。。

代码如下:

/**
 * 提供两个方法:
 * 一是转换自定义树形对象数据为a-tree识别的树形对象列表
 * 二是将数据库存储的已分配id列表重新转化为checkedList
 * 
 * @param {string} idKey - 数据项 ID 的键名,默认为 'id'
 * @param {string} nameKey - 数据项名称的键名,默认为 'name'
 * @param {string} childrenKey - 子节点列表的键名,默认为 'children'
 */
export const useTreeConverter = (
  idKey: string = 'id',
  nameKey: string = 'name',
  childrenKey: string = 'children'
) => {
  /**
   * 转换对象
   * @param data 树形结构数据
   * @returns 返回UI组件认可的包含key、title、children属性的树形结构数据
   */
  const convertTree = (data: any[]): any[] => {
    return data.map((item) => ({
      key: item[idKey],
      title: item[nameKey],
      children:
        item[childrenKey] && item[childrenKey].length > 0 ? convertTree(item[childrenKey]) : []
    }))
  }

  /**
   *
   * @param savedKeys 授权已分配的ID列表
   * @param treeData 框架规定的treeData
   * @returns
   */
  const loadCheckState = (savedKeys: number[] = [], treeData: any[]) => {
    //选中数组
    const checkedKeysTemp: number[] = []
    //半选中数组
    const halfCheckedKeysTemp: number[] = []

    const checkNodeStatus = (node) => {
      //若本节点为叶子节点且ID列表包含节点的key值,则加入到选中数组中
      if (node.children.length === 0 && savedKeys.includes(node.key)) {
        checkedKeysTemp.push(node.key)
      }
      //若本节点为非叶子节点
      if (node.children.length > 0) {
        const isAllLeaf = node.children.every((child) => child.children.length === 0)
        //子节点都为叶子节点
        if (isAllLeaf) {
          //若叶子节点被选中,则加入到选中数组中
          for (let item of node.children) {
            if (savedKeys.includes(item.key)) {
              checkedKeysTemp.push(item.key)
            }
          }
          //若子节点都被选中,则该节点为被选中
          const allChildrenChecked = node.children.every((child) => savedKeys.includes(child.key))
          if (allChildrenChecked) {
            checkedKeysTemp.push(node.key)
            console.log(checkedKeysTemp)
          } else {
            //若子节点部分被选中,则该节点为半选中
            const someChildrenChecked = node.children.some((child) => savedKeys.includes(child.key))
            if (someChildrenChecked) {
              halfCheckedKeysTemp.push(node.key)
            }
          }
        } else {
          //若子节点不是都为叶子节点
          for (let item of node.children) {
            //子节点进行迭代
            if (item.children.length > 0) {
              item.children.forEach(checkNodeStatus)
            } else {
              checkNodeStatus(item)
            }
          }
          //迭代完子节点,继续判断该节点是否被选中
          const allChildrenChecked = node.children.every((child) =>
            checkedKeysTemp.includes(child.key)
          )
          //若子节点都被选中且不是半选中,则该节点为被选中
          if (allChildrenChecked) {
            checkedKeysTemp.push(node.key)
          } else {
            //若子节点部分被选中,则该节点为半选中
            const someChildrenChecked = node.children.some((child) => savedKeys.includes(child.key))
            if (someChildrenChecked) {
              halfCheckedKeysTemp.push(node.key)
            }
          }
        }
      }
    }

    // treeData 是你的树形结构的数据
    treeData.forEach(checkNodeStatus)

    return checkedKeysTemp
  }

  return {
    convertTree,
    loadCheckState
  }
}

由于a-tree的组件还是经常使用的,我将此算法封装为组合式函数useTreeConverter.ts中了,后面其他代码,也能复用该算法逻辑。

它包含两个逻辑:

一是将自定义的树形结构转换为组件识别的形如{children:‘children’, title:‘title’, key:‘key’ }的树形结构TreeData

二是给定形如[1,3,5,7,11]的授权ID列表和转换后的树形结构TreeData通过递归迭代的方式还原出哪些是checkedKeys的值。

该组合式函数的代码写一次就够了,后面其他使用a-tree的组件都用得上。提供2个服务端返回的授权列表和树形结构的参数输入,再调用提供的convertTreeloadCheckState的2个函数就可以得出结果了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/874563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

天通报警呼叫柱:为边防哨所筑起坚固的通信堡垒

一、背景 边防哨所是国家安全的重要防线&#xff0c;肩负着守护边境安全、维护国家主权和领土完整的神圣使命。由于边防哨所通常位于地理位置偏远、环境恶劣的地区&#xff0c;通信问题成为影响边防工作的重要因素&#xff0c;给边防官兵的日常工作和应急响应带来了不小的挑战…

vue3封装数字上下滚动翻牌器,

优点&#xff1a;可以传入字符串设置初始数字位数&#xff0c;也可以直接传入数字&#xff0c;让他自己根据位数渲染 组件代码&#xff1a; <template><div class"count-flop" :key"compKey"><!-- --><div:class"item ! . ?…

欺诈文本分类检测(十四):GPTQ量化模型

1. 引言 量化的本质&#xff1a;通过将模型参数从高精度&#xff08;例如32位&#xff09;降低到低精度&#xff08;例如8位&#xff09;&#xff0c;来缩小模型体积。 本文将采用一种训练后量化方法GPTQ&#xff0c;对前文已经训练并合并过的模型文件进行量化&#xff0c;通…

判断奇偶数的小妙招

要判断一个数是奇数还是偶数&#xff0c;一般首先想到的都是对2取余&#xff0c;但其实有更高明的算法。 首先咱们要知道一个知识点&#xff1a;偶数的二进制末位为0&#xff0c;奇数的二进制末位为1。 这是进位制本身的规则决定的&#xff0c;二进制是“逢二进一”。如果末位…

Docker 学习 Day 2

docker 基本命令和操作 学习视频一、docker 常用命令1、帮助启动类命令2、镜像命令2.1、docker images2.2、docker search 某个 xxx 镜像的名字2.3、docker pull 某个 xxx 镜像的名字2.4、docker system df2.5、docker rmi 某个 xxx 镜像的名字 ID2.6、面试题&#xff1a;谈谈 …

谷歌seo网址如何快速被收录?

想让你的网站快速被搜索引擎收录&#xff0c;可以采取几种不同的策略。首先&#xff0c;确保你的网站内容丰富、有价值&#xff0c;搜索引擎更喜欢收录内容质量高的网站。同时&#xff0c;增强网站的外链建设&#xff0c;做好这些站内优化&#xff0c;接下来就是通过谷歌搜索控…

windows下自启springboot项目(jar+nginx)

1、将springboot项目打包为jar 2、新建文本文档 test.txt&#xff0c;并输入 java -jar D:\test\test.jar&#xff08;修改为自己的jar包位置&#xff09; 保存 然后修将后缀名改为 .bat 3、在同一目录再新建 文本文档test.txt&#xff0c;输入以下内容&#xff0c;&…

“杏鲍菇驱动机器人创新前行:康奈尔大学最新研究亮相Science子刊“

未来科技新篇章&#xff1a;杏鲍菇操控下的机器人奇旅&#xff01; 在这个日新月异的科技时代&#xff0c;你或许听说过机器人由AI驱动、由人脑操控&#xff0c;但你是否能想象&#xff0c;一颗看似平凡的杏鲍菇也能成为控制机器人的“大脑”&#xff1f; 没错&#xff0c;这不…

对抗性EM用于变分深度学习:在低剂量PET和低剂量CT中的半监督图像质量增强应用|文献速递--Transformer架构在医学影像分析中的应用

Title 题目 Adversarial EM for variational deep learning: Application to semi-supervised image quality enhancement in low-dose PET and low-dose CT 对抗性EM用于变分深度学习&#xff1a;在低剂量PET和低剂量CT中的半监督图像质量增强应用 01 文献速递介绍 医学影…

新专利:作物生长期预测方法及装置

近日,国家知识产权局正式授权了一项由北京市农林科学院智能装备技术研究中心、江苏省农业科学院联合申请的发明专利"作物生长期预测方法及装置"(专利号:ZL 2024 1 0185298.1)。该专利由 于景鑫 、任妮、吕志远、李友丽、吴茜等发明人耗时多年潜心研发&#xff0c;犹如…

6、关于Medical-Transformer

6、关于Medical-Transformer Axial-Attention原文链接&#xff1a;Axial-attention Medical-Transformer原文链接&#xff1a;Medical-Transformer Medical-Transformer实际上是Axial-Attention在医学领域的运行&#xff0c;只是在这基础上增加了门机制&#xff0c;实际上也就…

Java入门:08.Java中的static关键字01

1 static关键字 可以修饰属性变量&#xff0c;方法和代码段 static修饰的属性称为静态属性或类属性&#xff0c; 在类加载时就在方法区为属性开辟存储空间&#xff0c;无论创建多少个对象&#xff0c;静态属性在内存中只有一份。 可以使用 类名.静态属性 的方式引用 static修饰…

无人机动力系统设计之桨叶推力计算

无人机动力系统设计之桨叶推力计算 1. 源由2. 关键参数2.1 特性参数2.1.1 材质&#xff08;Material&#xff09;2.1.2 叶片数量&#xff08;Number of Blades&#xff09;2.1.3 重量&#xff08;Weight&#xff09;2.1.4 噪音水平&#xff08;Noise Level&#xff09; 2.2 安装…

一文为你详解期权波动率是什么?

今天期权懂带你了解一文为你详解期权波动率是什么&#xff1f;采用合适的期权组合来对冲或利用波动率变化带来的机会。不同策略适用于不同的市场条件和投资目标。 期权波动率 假如我们为地震灾害去买一份保险&#xff0c;你认为什么样地震的保险费会更贵呢&#xff0c;是深圳…

备忘录模式memento

学习笔记&#xff0c;原文链接 https://refactoringguru.cn/design-patterns/memento 允许生成对象状态的快照并在以后将其还原。备忘录不会影响它所处理的对象的内部结构&#xff0c; 也不会影响快照中保存的数据。

2024年湖北交安ABC公路安全员C证报考今时不同往日

2024年湖北交安ABC公路安全员C证报考今时不同往日 之前的交安ABC&#xff0c;你爱搭不理&#xff0c;现在的交安ABC&#xff0c;你高攀不起。真的应了这句话。所以建筑行业考证要趁早&#xff0c;别等要求严了你想报却缺东少西的。湖北交安ABC大变天了。 2024年之前报考湖北交…

初识Maven:Java项目管理工具

实际开发中&#xff0c;伴随着项目规模的增长&#xff0c;依赖管理和构建自动化变得至关重要&#xff0c;一套标准化的项目结构有助于更好的开发项目、简化这项任务&#xff08;真的不是强迫症&#xff09; Maven&#xff0c;作为 Apache Software Foundation 维护的项目管理工…

【Unity面经】性能优化篇

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…

SpringBoot开发——整合Logbook进行HTTP API请求响应日志输出

文章目录 1. 简介依赖管理2. 实战案例2.1 基本用法2.2 结合Logback日志记录到文件2.3 自定义核心类Logbook2.4 自定义日志输出Sink2.5 与RestTemplate集成1. 简介 记录HTTP API请求响应日志对于监控、调试和性能优化至关重要。它帮助开发者追踪API的使用情况,包括请求来源、参…

2010-2022年各省乡村振兴新质生产力相关变量数据(40+指标)

2010-2022年各省乡村振兴新质生产力相关变量数据&#xff08;40指标&#xff09; 1、时间&#xff1a;2010-2022年 2、来源&#xff1a;统计年鉴、能源统计年鉴、农村统计年鉴、人口和就业统计年鉴、城乡建设统计年鉴以及各省份统计年鉴 3、指标&#xff1a;省份、年份、分地…