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();  
}

大家有更好的方法實現這需求,請留言,謝謝
注:愛護原創,轉載請說明出處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章