js实现树级递归,通过js生成tree树形菜单(递归算法)

方法封装:


/**
 * 数据转换为树形(递归),示例: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。
  • 想到了再补充。。。
原文地址:https://www.cnblogs.com/jardeng/p/13541640.html