方法封装:


/**
* 数据转换为树形(递归),示例:toTreeByRecursion(source, 'id', 'parentId', null, 'children')
* @param {Array} source 数据
* @param {String} idField 标识字段名称
* @param {String} parentIdField 父标识字段名称
* @param {Any} parentIdNoneValue 父级标识空值
* @param {String} childrenField 子节点字段名称
* @param {Object} treeOption tree树形配置
*/function toTreeByRecursion (
source = [],
idField = 'id',
parentIdField = 'parentId',
parentIdNoneValue = '',
childrenField = 'children',
treeOption = undefined
) {
const treeOptions = {
enable: false, // 是否开启转tree插件数据
keyField: 'key', // 标识字段名称,默认为key
valueField: 'value', // 值字段名称,默认为value
titleField: 'title', // 标题字段名称,默认为title keyFieldBind: 'id', // 标识字段绑定字段名称,默认为id
valueFieldBind: 'id', // 值字段名称绑定字段名称,默认为id
titleFieldBind: 'name' // 标题字段名称绑定字段名称,默认为name
}
// 合并tree树形配置
if (treeOption) {
Object.assign(treeOptions, treeOption)
} // 对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(source))
return cloneData.filter(parent => {
// 返回每一项的子级数组
const branchArr = cloneData.filter(child => parent[idField] === child[parentIdField]) // 绑定tree树形配置
if (treeOptions.enable) {
branchArr.map(child => {
child[treeOptions.keyField] = child[treeOptions.keyFieldBind]
child[treeOptions.valueField] = child[treeOptions.valueFieldBind]
child[treeOptions.titleField] = child[treeOptions.titleFieldBind]
return child
})
} // 如果存在子级,则给父级添加一个children属性,并赋值,否则赋值为空数组
if (branchArr.length > 0) {
parent[childrenField] = branchArr
} else {
parent[childrenField] = []
} // 绑定tree树形配置
if (treeOptions.enable) {
parent[treeOptions.keyField] = parent[treeOptions.keyFieldBind]
parent[treeOptions.valueField] = parent[treeOptions.valueFieldBind]
parent[treeOptions.titleField] = parent[treeOptions.titleFieldBind]
} return parent[parentIdField] === parentIdNoneValue // 返回第一层
})
}

使用示例:


var jsonData = [
{
id: '1',
name: '1',
parentId: null,
rank: 1
},
{
id: '2',
name: '1-1',
parentId: '1',
rank: 1
},
{
id: '3',
name: '1-2',
parentId: '1',
rank: 1
}, {
id: '4',
name: '2',
parentId: null,
rank: 1
},
{
id: '5',
name: '2-1',
parentId: '4',
rank: 1
},
{
id: '6',
name: '2-2',
parentId: '4',
rank: 1
},
{
id: '7',
name: '2-2-1',
parentId: '6',
rank: 1
}
]
const treeOption = {
enable: false, // 是否开启转tree插件数据
keyField: 'key', // 标识字段名称
valueField: 'value', // 值字段名称
titleField: 'title', // 标题字段名称 keyFieldBind: 'id', // 标识字段绑定字段名称
valueFieldBind: 'id', // 值字段名称绑定字段名称
titleFieldBind: 'name' // 标题字段名称绑定字段名称
}
const treeData = toTreeByRecursion(jsonData, 'id', 'parentId', null, 'children', treeOption)
console.log(treeData)

说明:


  • parentIdNoneValue 父级标识空值这个参数如果跟你数据无父级时的值不一致时,就配置这个参数。比如:这里默认值为null,你根节点parentId的值为-1或''。
  • treeOption 参数可以不传,如果要绑定tree树形控件(一般都会有key、value、title这三个字段),那就需要配置这个参数,如果参数默认的配置跟你的不一样,那就通过参数覆盖的方式重新定义。
  • treeOption 的三个绑定字段是指绑定你数据中的字段,实质就是把原数据字段绑定的tree树形控件需要的三个字段key、value、title。
  • 想到了再补充。。。

js实现树级递归,通过js生成tree树形菜单(递归算法)的更多相关文章

  1. js模仿块级作用域(js没有块级作用域私有作用域)

    js模仿块级作用域(js没有块级作用域私有作用域) 一.总结 1.js没有块级作用域:在for循环中定义的i,出了for循环还是有这个i变量 2.js可以模拟块级作用域:用立即执行的匿名函数:(匿名函 ...

  2. 菜鸟笔记:node.js+mysql中将JSON数据构建为树(递归制作树状菜单数据接口)

    初学Web端开发,今天是第一次将所学做随笔记录,肯定存在多处欠妥,望大家海涵:若有不足,望大家批评指正. 进实验室后分配到的第一个项目,需要制作一个不确定层级树形菜单的数据接口,对于从来没实战编过程的 ...

  3. js无限级树菜单

    以前做网站,树形菜单一般都很简单,自己定义风格样式,简单的js控制,后来原来网上很多文章都在讨论Js树型菜单,看了几个实例,发现这个树比较简单好用. http://hovertree.com/texi ...

  4. 用Vue.js递归组件构建一个可折叠的树形菜单

    在Vue.js中一个递归组件调用的是其本身,如: Vue.component('recursive-component', {   template: `<!--Invoking myself! ...

  5. Vue.js递归组件实现动态树形菜单

    使用Vue递归组件实现动态菜单 现在很多项目的菜单都是动态生成的,之前自己做项目也是遇到这种需求,翻看了官网案例,和网上大神的案例.只有两个感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神 ...

  6. Vue.js 递归组件实现树形菜单

    最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: import Vue from 'vue' Vue.config.debug = tr ...

  7. 6个函数的output看JS的块级作用域

    1. var output = 0; (function() { output++; }()); console.log(output); 函数对全局的output进行操作,因为JS没有块级作用域,所 ...

  8. 下拉的DIV+CSS+JS二级树型菜单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. JQuery 树状结构 jQuery-treeview.js 插件

    由简入繁实现Jquery树状结构 在项目中,我们经常会需要一些树状结构的样式来显示层级结构等,比如下图的样式,之前在学.net的时候可以直接拖个服务端控件过来直接使用非常方便.但是利用Jquery的一 ...

随机推荐

  1. 提取txt文本有效内容

    原理: 1.使用足够多的垃圾邮件和非垃圾邮件的内容作为训练集 2.读取全部训练集 删除其中的干扰字符 [ ] ,* . 进行分词 删除长度为 1 的单个字符 3.统计全部训练集中每个有效词汇的出现次数 ...

  2. Python os.ttyname() 方法

    概述 os.ttyname() 方法用于返回一个字符串,它表示与文件描述符fd 关联的终端设备.如果fd 没有与终端设备关联,则引发一个异常.高佣联盟 www.cgewang.com 语法 ttyna ...

  3. Python time sleep()方法

    描述 Python time sleep() 函数推迟调用线程的运行,可通过参数secs指秒数,表示进程挂起的时间.高佣联盟 www.cgewang.com 语法 sleep()方法语法: time. ...

  4. ABPHelper.CLI及其依赖项简单介绍

    目录 目录 ABPHelper.CLI 入门 使用指南 命令行 技术点如下 Scriban 通过Microsoft.Extensions.FileProviders.Embedded获取嵌入资源 通过 ...

  5. 当asp.net core偶遇docker一(模型验证和Rabbitmq 一)

    比如我们有一些设计,依赖于某些软件,比如rabbitmq 当管理员功能,反复错误三五次之后,就发送一条消息到队列里去,我们又不希望对原先设计带来侵入式的改变业务 这个时候,我们就可以在模型验证里面加入 ...

  6. 【BZOJ2821】作诗 题解(分块+前缀和)

    前言:世间还有这么卡常的题…… ------------------ 题目链接 题目大意:给定长度为$n$的序列${a_i}$.有$m$次询问,问$[l,r]$内出现正偶数次的数字有多少个. 这题跟蒲 ...

  7. 【NOIP2016】天天爱跑步 题解(LCA+桶+树上差分)

    题目链接 题目大意:给定一颗含有$n$个结点的树,每个结点有一个权值$w$.给定$m$条路径,如果一个点与路径的起点的距离恰好为$w$,那么$ans[i]++$.求所有结点的ans. 题目分析 暴力的 ...

  8. day23:单继承&多继承&菱形继承&__init__魔术方法

    1.单继承 1.1 关于继承的一些基本概念 1.2 子类可以调用父类的公有成员 1.3 子类无法调用父类的私有成员 1.4 子类可以改写父类的方法 2.多继承 2.1 多继承的基本语法 2.2 sup ...

  9. CSS品控与流程

    精通CSS意味着不仅能写出可用的标记和样式,还能让代码好阅读.方便移植.易维护. 1.外部代码质量:调试CSS 外部代理质量就是用户能体验到的最终结果.主要体现在几个方面. 正确性.CSS属性名都写对 ...

  10. Unity目录结构设置

    摄像机 Main Camera 跟随主角移动,不看 UI 剧情摄像机 当进入剧情时,可以关闭 main camera,启用剧情摄像机,不看 UI UI 摄像机 看 UI Unity编辑器常用的sett ...