React antd tree树组件 - 父子节点没有自动关联情况下 - 显示半选、全选状态以及实现父子节点互动

实现的效果图如下:
在这里插入图片描述
如Ant Design Vue 中所示,并没有提供获取半选节点的方法,当设置checked和checkStrictly时,父子节点也不再自动关联了
在这里插入图片描述

前提:从后端可以获取的数据分别是完整的树型数据、所有选中的节点数据(一个数组、同时包含 父节点和子节点),具体的大概数据可以看下面
树形结构(二重),parId是-1则表示是父节点数据:
在这里插入图片描述
这是返回的已选中节点的数组:
在这里插入图片描述
下面是具体的代码:

state = {
  treeData: [], // 树形数据
  checkedKeys: [],
  checkable: false, // 因为我的页面是树型结构在页面右侧,根据左侧显示具体(看自己需求)
  loading: true,
  halfChecked: [], // 半选
  checked: [] // 全选
};

render() {
const { checkedKeys, treeData, checkable, halfChecked, checked, loading } = this.state
<Tree
  ref={r => this.treeRef = r}
  className={styles.menuTree}
  blockNode
  showLine
  // selectable={false}
  checkable={checkable}
  defaultExpandAll
  // checkedKeys={checkedKeys}
  checkedKeys={{
    checked,
    halfChecked
  }}
  checkStrictly
  onCheck={({ checked: ck, halfChecked: hc, ...oth }, { checked, node: { props: { dataRef } } }) => {
    // 选择
    if (checked && dataRef.id) {
      ck = ck.filter(i => i != `${dataRef.id}`).concat(`${dataRef.id}`);
    }
    // 如果有子级,则全部选上
    if(dataRef.parId == '-1'&&dataRef.childList&&dataRef.childList.length > 0){
      const kidKeys = this.getCKidKey(dataRef.childList);
      if(checked){
        ck = ck.concat(kidKeys);
      }else{
          ck = ck.filter(k=>{
          const bo= !kidKeys.includes(k);
          return bo;
        })
      }
    }
    // 如果选中的是子级,其父级也默认选中;取消选中时如果其父级下无选中内容,父级取消选中
    if(dataRef.parId != '-1'){
      if(checked){
        ck.push(dataRef.parId.toString())
        ck = Array.from(new Set(ck));
      }else{
        const ckId = dataRef.id; // 当前选中子级的id
        const ckParId = dataRef.parId; // 当前选中de子级的父级id
        const childList = this.treeMap[ckParId]?.childList; // 当前选中子级的父级 包含的子级
        let isHave = false // 父级下的子级是否有选中的,默认无选中的
        childList.forEach((item => {
          const ass = ck.includes(item.id.toString())
          if(ass) { // 如果还有选中的
            isHave = true
            return
          }
        }))
        if(!isHave){
          ck = ck.filter(item => item != ckParId)
        }
      }
    }
    const lastAllData = Array.from(new Set([...ck, ...hc]))
    this.parentStatus(lastAllData);
  }}
>
  {this.renderTreeNodes(treeData)}
</Tree>
}

主要是onCheck方法里面的处理,下面是用到的一些方法

// 所有已选节点分成两组,全选、半选。
parentStatus = (checked) => { // 这里的checked是指传入所有已选节点
  const { treeData } = this.state; 
  const pData = [] // 半选的父级id数组
  const allPData = [] // 全选的父级id数组
  checked.forEach(i => {
    treeData.forEach(j =>{
      if(i == j.id){ // 如果有选中的父级
        const ckPList = [] // 选中父级的子级数组
        j.childList.forEach(r =>{
          ckPList.push(r.id.toString())
        })
        if(this.isContained(checked, ckPList)){
          allPData.push(j.id.toString())
        }else{
          pData.push(i.toString())
        }
      }
    })
  })
  const halfCkData = [] // 半选状态数据
  const allCkData = [] // 全选状态数据
  for(const i of checked){
    pData.includes(i)&&halfCkData.push(i);
    !pData.includes(i)&&allCkData.push(i);
  }
  this.setState({
    checked: allCkData,
    halfChecked: halfCkData,
  })
}

// 判断一个数组是否包含了另一个数组的全部元素
isContained = (a, b) => {
  // a和b其中一个不是数组,直接返回false
  if (!(a instanceof Array) || !(b instanceof Array)) return false;
  const len = b.length;
  // a的长度小于b的长度,直接返回false
  if (a.length < len) return false;
  for (let i = 0; i < len; i++) {
      if (!a.includes(b[i])) return false;
  }
  return true;
};

// 
ckeys = []

getKidKey = kids => {
  kids.reduce((p, c, ci, arr) => {
    p.push(c.key);
    if (c.children) {
      this.getKidKey(c.children);
    }
    return p;
  }, this.ckeys);
}

getCKidKey = kids => {
  this.getKidKey(kids);
  const cks = [...this.ckeys];
  this.ckeys = []
  return cks;
}

ps因为代码是随着需求优化慢慢增加的,所以命名可能有点乱,方法也是比较杂又多,写出来了就随它了,懒得优化就这样了。如果有帮助到你的话就很nice啦~

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

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

相关文章

前后端分离------后端创建笔记(05)用户列表查询接口(下)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

线性代数(三) 线性方程组向量空间

前言 如何利用行列式&#xff0c;矩阵求解线性方程组。 线性方程组的相关概念 用矩阵方程表示 齐次线性方程组&#xff1a;Ax0&#xff1b;非齐次线性方程组&#xff1a;Axb. 可以理解 齐次线性方程组 是特殊的 非齐次线性方程组 如何判断线性方程组的解 其中R(A)表示矩阵A的…

【前端】CSS水平居中的6种方法

文章目录 flex绝对定位margin:auto绝对定位margin:负值定位transformtext-align: center;margin: 0 auto;思维导图 后文&#xff1a;【前端】CSS垂直居中的7种方法_karshey的博客-CSDN博客 左右两边间隔相等的居中 flex display: flex;justify-content: center; <div clas…

2023国赛数学建模E题思路分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…

腾讯云CVM服务器端口在安全组中打开!

腾讯云服务器CVM端口怎么开通&#xff1f;腾讯云服务器端口是通过配置安全组规则来开通的&#xff0c;腾讯云服务器网以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0…

Python数学函数、字符串和对象

学习目标&#xff1a; 使用math模块中的函数解决数学问题表示和处理字符串和字符使用ASCII和Unicode对字符编码使用ord函数获取一个字符的数值编码以及使用chr函数将一个数值编码转换成一个字符使用转义序列表示特殊字符调用带参数end的print函数使用str函数将数字转换成字符串…

【软件工程】面向对象方法-RUP

RUP&#xff08;Rational Unified Process&#xff0c;统一软件开发过程&#xff09;。 RUP特点 以用况驱动的&#xff0c;以体系结构为中心的&#xff0c;迭代增量式开发 用况驱动 用况是能够向用户提供有价值结果的系统中的一种功能用况获取的是功能需求 在系统的生存周期中…

如何搭建个人邮件服务hmailserver并实现远程发送邮件

文章目录 1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpolar内网映射工…

iOS手机无法安装Charles 的ssl证书

问题描述 iOS客户端安装证书时一直卡在下载这一步&#xff0c;无法抓包 1、打开Charles&#xff0c;选择help→SSL Proxying→Install Charles Root Certificate on a Mobile Device or Remote Browser 2、按照步骤1中的提示进行操作&#xff0c;手机连接电脑代理&#xff0c;…

OpenCV图像处理——轮廓检测

目录 图像的轮廓查找轮廓绘制轮廓 轮廓的特征轮廓面积轮廓周长轮廓近似凸包边界矩形最小外接圆椭圆拟合直线拟合 图像的矩特征矩的概念图像中的矩特征 图像的轮廓 查找轮廓 binary,contours,hierarchycv.findContours(img,mode,method)绘制轮廓 cv.drawContours(img,coutours…

4WRZ25E3-220-5X/6A24NZ4/D3M不带位移反馈比例阀放大器

该先导阀是一个由比例电磁铁控制的三通减压阀&#xff0c;它的作用是将一个输入信号转化为一个与其成比例的压力输出信号&#xff0c;可用于所有的4WRZ...和5WRZ...型比例阀的控制。比例电磁铁是可调试&#xff0c;湿式直流电磁铁结构&#xff0c;带中心螺纹&#xff0c;线圈可…

如何使用Redis实现内容推送功能

导读 在日常使用中&#xff0c;我们经常能看见内容推送功能。 常见的场景有&#xff0c;比如你在bilibili关注了某个up主&#xff0c;当up主发布视频后&#xff0c;就会推送到你的收件箱或者是动态中&#xff0c;让粉丝能够及时得知所关注的人发布了内容。 又比如朋友圈&…

【设备树笔记整理4】内核对设备树的处理

1 从源头分析_内核head.S对dtb的简单处理 1.1 bootloader向内核传递的参数 &#xff08;1&#xff09;bootloader启动内核时&#xff0c;会设置r0&#xff0c;r1&#xff0c;r2三个寄存器&#xff1a; r0一般设置为0;r1一般设置为machine_id (在使用设备树时该参数没有被使用…

Nginx的块、变量以及重定向

目录 绪论 1、location匹配 1.1 常见的Nginx正则表达式 1.2 正则表达式&#xff1a;匹配的是文件内容 1.3 location匹配uri 1.4 location常用的匹配规则 1.5 location优先级 1.6 匹配小结 1.7 生产环境中的匹配规则 2、nginx的内置变量 3、rewrite 3.1 rewrite作用 …

【考研数学】概率论与数理统计 | 第一章——随机事件与概率(1)

文章目录 一、随机试验与随机事件1.1 随机试验1.2 样本空间1.3 随机事件 二、事件的运算与关系2.1 事件的运算2.2 事件的关系2.3 事件运算的性质 三、概率的公理化定义与概率的基本性质3.1 概率的公理化定义3.2 概率的基本性质 写在最后 一、随机试验与随机事件 1.1 随机试验 …

优测云服务平台|【压力测试功能升级】轻松完成压测任务

一、本次升级主要功能如下&#xff1a; 1.多份报告对比查看测试结果 2.报告新增多种下载格式 Word格式Excel格式 3.新增多种编排复杂场景的控制器 漏斗控制器并行控制器事务控制器仅一次控制器分组控制器集合点 4.新增概览页面&#xff0c;包含多种统计维度 二、报告对比…

spring-boot-maven-plugin插件详解

一、 为什么Spring Boot项目自带这个插件 当我们在SpringBoot官方下载一个脚手架时,会发现pom.xml会自带spring-boot-maven-plugin插件 那为什么会自带这个插件呢&#xff1f; 我们知道Spring Boot项目&#xff0c;是可以通过java -jar 包名启动的 打包命令 mvn clean pac…

Rust 编程小技巧摘选(8)

目录 Rust 编程小技巧(8) 1. 取整函数 floor() 2. 取整函数ceil() 3. 取整函数 round() 4. 保留小数位数 5. 字符串转整数 unwrap() unwrap_or() Rust 编程小技巧(8) 1. 取整函数 floor() floor函数对浮点数进行向下取整 示例代码&#xff1a; fn main() {let x: …

【数据结构与算法——TypeScript】图结构(Graph)

【数据结构与算法——TypeScript】 图结构(Graph) 认识图结构以及特性 什么是图? 在计算机程序设计中&#xff0c;图结构 也是一种非常常见的数据结构。 但是&#xff0c;图论其实是一个非常大的话题 认识一下关于图的一些内容 图的抽象数据类型一些算法实现。 什么是图?…

一百五十五、Kettle——Linux上安装的kettle9.3连接MySQL数据库

一、目的 kettle9.3在Linux上成功安装后&#xff0c;就建立数据库连接&#xff0c;第一个就是MySQL数据库 二、前提准备 提前准备好MySQL驱动包 &#xff08;一&#xff09;MySQL版本 &#xff08;二&#xff09;注意&#xff1a;由于我的MySQL版本比较高&#xff0c;所以特…