如何用js将后台扁平的码表数据,转换为无限层级的树形结构,递归删除树形结构

一、前端扁平数据转换为树结构

先上代码,这个我刚刚上网上找了,很多人已经发过了,我还以为是公司里面人独创的呢
后面有详细的解释
这个主要是面向实际开发环境的,你可以省略掉除了source的所有其它参数,因为它们是为了通用性,因为总有些人十分具备没必要的个人特色
比如所有人都用0来作为码表根结点parentId,而它非要用12580
/**
 * 构造树型结构数据
 * @param {*} source 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 * @param {*} rootId 根Id 默认 0
 */
export function treeData (source, id, parentId, children, rootId) {
  id = id || 'id'
  parentId = parentId || 'parentId'
  children = children || 'children'
  rootId = rootId || 0
  const cloneData = JSON.parse(JSON.stringify(source))// 对源数据深度克隆
 return cloneData.filter(father => {
    const branchArr = cloneData.filter(child => father[id] == child[parentId])// 返回每一项的子级数组
    branchArr.length > 0 ? father[children] = branchArr : delete father[children]// 如果存在子级,则给父级添加一个children属性,并赋值
    return father[parentId] == rootId // 返回第一层
  })
}

最近在公司整合项目,发现后端这块后台统一返回的都是简单的扁平数据

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

处理树形结构的代码主要写在前端,我们来一步一步分析
/**
 * 构造树型结构数据
 * @param {*} source 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 * @param {*} rootId 根Id 默认 0
 */
export function treeData (source, id, parentId, children, rootId) {
  id = id || 'id'
  parentId = parentId || 'parentId'
  children = children || 'children'
  rootId = rootId || 0
  const cloneData = JSON.parse(JSON.stringify(source))// 对源数据深度克隆
 return cloneData.filter(father => {
    /* 
      father[id] === father.id     ,取的都是father对象中的id属性值
      cloneData.filter(child => father[id] === child[parentId])//就是将所有parentId = 当前对象id的数组过滤出来
    */
    const branchArr = cloneData.filter(child => father[id] == child[parentId])// 返回每一项的子级数组
    /* 
      branchArr.length > 0  如果大于0表示有子级  
        father[children] = branchArr 给father添加一个children属性,并将刚才的子级数组赋值给children属性
      
      delete father[children] 删除father对象的children属性
        delete:delete操作符,用于删除指定对象的某个属性
       
    */
    branchArr.length > 0 ? father[children] = branchArr : delete father[children]// 如果存在子级,则给父级添加一个children属性,并赋值
    
    /* 
      father[parentId] == rootId,判断father.parentId是否等于rootId,如果等于就是true,返回这条数据不被过滤掉
    */
    return father[parentId] == rootId // 返回第一层
  })
}

为了通用性的考虑声明
在这里插入图片描述
解决改变原数组的诟病
在这里插入图片描述
过滤代码
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、后端递归删除树形结构

在这里插入图片描述

1、controller

/**
	 * 删除${tableComment}
	 * @Param id 节点id
	 */
	@PostMapping("remove/{id}")
	public R remove(@PathVariable String id)
	{		
		return toAjax(oeCourseSubjectService.deleteOeCourseSubjectById(id));
	}

2、mapper

用到的有selectOeCourseSubjectList,selectOeCourseSubjectById,selectOeCourseSubjectByParentId,deleteOeCourseSubjectById

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.edu.imau.zy.online_education.mapper.OeCourseSubjectMapper">
    
    <resultMap type="OeCourseSubject" id="OeCourseSubjectResult">
        <result property="id"    column="id"    />
        <result property="title"    column="title"    />
        <result property="parentId"    column="parent_id"    />
        <result property="sort"    column="sort"    />
        <result property="gmtCreate"    column="gmt_create"    />
        <result property="gmtModified"    column="gmt_modified"    />
    </resultMap>

    <sql id="selectOeCourseSubjectVo">
        select id, title, parent_id, sort,gmt_create, gmt_modified from oe_course_subject
    </sql>

    <select id="selectOeCourseSubjectList" parameterType="OeCourseSubject" resultMap="OeCourseSubjectResult">
        <include refid="selectOeCourseSubjectVo"/>
        <where>
            <trim>
                <if test="title != null  and title != ''">and title = #{title}</if>
            </trim>
        </where>
        ORDER BY
            sort asc
    </select>
    
    <select id="selectOeCourseSubjectById" parameterType="String" resultMap="OeCourseSubjectResult">
        <include refid="selectOeCourseSubjectVo"/>
        where id = #{id}
    </select>
    <select id="selectOeCourseSubjectByParentId" parameterType="String" resultMap="OeCourseSubjectResult">
        <include refid="selectOeCourseSubjectVo"/>
        where parent_id = #{id}
    </select>
    <insert id="insertOeCourseSubject" parameterType="OeCourseSubject">
        insert into oe_course_subject
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="id != null  and id != ''">id,</if>
            <if test="title != null  and title != ''">title,</if>
            <if test="parentId != null  and parentId != ''">parent_id,</if>
            <if test="sort != null  and sort != ''">sort,</if>
            <if test="gmtCreate != null ">gmt_create,</if>
            <if test="gmtModified != null ">gmt_modified,</if>
         </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null  and id != ''">#{id},</if>
            <if test="title != null  and title != ''">#{title},</if>
            <if test="parentId != null  and parentId != ''">#{parentId},</if>
            <if test="sort != null  and sort != ''">#{sort},</if>
            <if test="gmtCreate != null ">#{gmtCreate},</if>
            <if test="gmtModified != null ">#{gmtModified},</if>
         </trim>
    </insert>

    <update id="updateOeCourseSubject" parameterType="OeCourseSubject">
        update oe_course_subject
        <trim prefix="SET" suffixOverrides=",">
            <if test="title != null  and title != ''">title = #{title},</if>
            <if test="parentId != null  and parentId != ''">parent_id = #{parentId},</if>
            <if test="sort != null  and sort != ''">sort = #{sort},</if>
            <if test="gmtCreate != null ">gmt_create = #{gmtCreate},</if>
            <if test="gmtModified != null ">gmt_modified = #{gmtModified},</if>
        </trim>
        where id = #{id}
    </update>

    <delete id="deleteOeCourseSubjectById" parameterType="String">
        delete from oe_course_subject where id = #{id}
    </delete>

    <delete id="deleteOeCourseSubjectByIds" parameterType="String">
        delete from oe_course_subject where id in 
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
    
</mapper>

3、service

/**
     * 删除在线教育课程分类信息
     * 
     * @param id 在线教育课程分类ID
     * @return 结果
     */
    @Override
    public int deleteOeCourseSubjectById(String id)
    {
        int index = 0;//定义一个int变量,用来返回删除了多少条数据
        
        List<OeCourseSubject> list = build(id);//获取递归后得到的所有需要删除的节点
        
        for (OeCourseSubject oeCourseSubject:list) {//遍历所有需要删除的节点
            //删除每一个节点
            oeCourseSubjectMapper.deleteOeCourseSubjectById(oeCourseSubject.getId());
            
            index++;
        }
        
        return index;
    }



    /**
     * 递归删除
     * 1、先获取所有子级(包括它自己),保存到一个容器中
     * 2、递归找出所有子级包括它本身的节点,保存到一个集合中
     * 3、遍历第二步得到的容器,删除每一条数据
     * @param id 根结点id
     * @return 封装了所有需要删除的菜单的容器
     */
    private List<OeCourseSubject> build(String id){
        //获取当前根节点对象
        OeCourseSubject treeNode = oeCourseSubjectMapper.selectOeCourseSubjectById(id);

        //用来保存所有需要删除菜单的容器
        List<OeCourseSubject> list = new ArrayList<>();

        //获取所有菜单
        List<OeCourseSubject> allList = oeCourseSubjectMapper.selectOeCourseSubjectList(null);

        list.add(treeNode);//将根结点添加到需要删除的容器

        findChildren(treeNode,allList,list);//进入递归

        return list;
    }

    /**
     * 递归获取所有需要删除节点
     * @param node 上级节点
     * @param allList 所有节点
     * @param list  需要删除的节点,将查询到的子节点全部添加进去即可
     */
    private void findChildren(OeCourseSubject node,List<OeCourseSubject> allList,List<OeCourseSubject> list){
        //判断当前节点是否有子节点
        if(oeCourseSubjectMapper.selectOeCourseSubjectByParentId(node.getId())!=null){
            //遍历节点
            for(OeCourseSubject ocs :allList){
                //判断parent_id是否等于当前节点id,找到所有直接子节点
                if (node.getId().equals(ocs.getParentId())){
                    list.add(ocs);//将此对象放在需要删除的集合中
                    findChildren(ocs,allList,list);//递归
                }
            }
        }
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值