zTree js 树形结构图算法

特殊的数据形成树形

  • 需求
  • 数据
  • 分析
  • 源码

需求

有两个数据类,一个是树形最底层的成员数据userList。一个树形中的部门数据depList,利用这两类数据形成树形。

数据

// 成员数据
const userList = [{
	id: 1,
	name: '张三',
	avatar: 'http://...',
	depId: 1
},{
	id: 2,
	name: '李四',
	avatar: 'http://...',
	depId: 2
}]

// 部门数据
const depList = [{
	id: 1,
	name: '部门1',
	parentId: 0
},{
	id: 2,
	name: '部门1',
	parentId: 1
}]

分析

形成树形网上有很多方法都可以,我这里根据需求进行改造,利用Object对象引用的特殊性(引用的Object改变后会改变原始Object)来实现这树形结构。再把树形数据填充到树形生成插件zTree中去。

考虑几点内容:

  1. 部门下是否无成员(出现空部门时当如何处理);
  2. 部门下是否无部门(出现部门下存在空部门时当如何处理);
  3. 部门下是否同时拥有成员及部门

源码

1、首先把成员数据按部门归个类

/**
* 对成员按depId分组
* @param {Array} d 成员数据
* return Object 以部门为键值的成员对象
*/
groupUser(d){
    var users = {}
    for(var i = 0; i < d.length; i++){
        if(users[d[i].depId]){
            users[d[i].depId].push(d[i])
        }else{
            users[d[i].depId] = [d[i]]
        }
    }
    return users;
}

2、再计算树形

/**
* 部门架构树形图
* @param {Array} d 部门信息
* return Object
*/
groupDep(d){
	// 拿取成员信息map
    var usersMap = this.groupUser(userList)

    // 将部门数据存储为以id为key的map
    var depMap = {}
    d.forEach(function (item){
        depMap[item.id] = item
    })
	var depTree = []
    d.forEach(function(item){
    	// 以当前遍历项的parentId,去depMap对象中找到索引的id(如找到则说明当前项存在父级)
        var parent = depMap[item.parentid]   
        // 以当前遍历项的id,去usersMap对象中找到索引的id                           
        var users = usersMap[item.id] 
        // 如果找到当前部门下的成员数据,那么把相关人员追加到此项中                                  
        if(users){                                                      
            if(item.children){
                item.children = item.children.concat(users)
            }else{
                item.children = users
            }
        }else{                                    
        	// 如果部门下无员工(此处处理部门下无成员时需要给当前部门添加一个属性depNone=true)
            var depChild;
            // 查找有无子部门
            for(var key in depMap){                 
                if(depMap[key].parentid == item.id) depChild = true;	// 如果不存
            }
            // 如果没有,就添加一个属性depNone=true
            // 此属性可用于zTree中,用来判断该层是否存在成员,方时可利用它来给isParent设为true,以文件夹的方法展示。
            if(!depChild) item.depNone = true;	
        }
        // 如果找到父级部门,那么说明此项不在顶级当中,需要把此项添加到对应的父级中
        if (parent) (parent.children || (parent.children = [])).push(item)
        //如果没有在depMap中找到对应的索引ID,那么直接把当前的item添加到depTree结果集中,作为顶级
        else depTree.push(item)                      
    })
    return depTree
}

最后再把zTree中设置isParent属性的方法贴出来

/**
* 设置zTree中的isParent属性
* @param {String} id 渲染zTree的domID
* return 无
*/
fixIcon(id){
    var treeObj = $.fn.zTree.getZTreeObj(id);
    //过滤出depNone属性为true的节点
    var folderNode = treeObj.getNodesByFilter(node => {return node.depNone});
    
    //遍历目录节点,设置isParent属性为true;
    folderNode = folderNode.map(item => {
		item.isParent = true;
	})
	//调用api自带的refresh函数。
    treeObj.refresh();  
}

大家有更好的方法实现这需求,请留言,谢谢
注:爱护原创,转载请说明出处

你可能感兴趣的:(javascript,数组)