SimpleAdmin手摸手教學之:基於Ant Design Tree組件實現樹形結構數據的異步加載

一、說明

當有一個樹形結構的數據有非常多個節點的時候,一次性加載所有節點會顯得過於臃腫,可能會對性能造成影響,正好Ant Design 的樹(Tree)組件支持異步加載,於是我就想把異步加載封裝爲一個組件,可以減少接口數據返回,點擊展開節點,動態加載數據。非常好用!

二、前端實現

需要接收一些值用來數據的初始化和格式化

const props = defineProps({
		//替換treeNode 中 children
		fieldNamesChildren: { type: String, default: 'children' },
		//替換treeNode 中 title
		fieldNamesTitle: { type: String, default: 'title' },
		//替換treeNode 中 key
		fieldNamesKey: { type: String, default: 'id' },
		//初始數據
		treeData: { type: Function, required: true },
		//父Id字段
		parentIdColumn: { type: String, default: 'parentId' },
		//默認頂級父Id值
		topValue: { default: 0 }
	})

以組織樹爲例,需要異步加載的時候,由tree組件換成lazyTree組件就行

<lazy-tree field-names-title="name" :treeData="loadTreeData" @select="treeSelect"></lazy-tree>

默認需要傳treeData屬性,也就是去請求後端去獲取數據的方法,這個方法需要有一個參數parameter,當展開節點的時候會請求這個方法並帶上父ID去查詢。

	const loadTreeData = (parameter) => {
		return genTestApi.orgTree(parameter).then((res) => {
			return res
		})
	}

首次加載組件會調用一次獲取節點數據方法。

	onMounted(() => {
		let parameter = {} //查詢參數
		parameter[props.parentIdColumn] = props.topValue //默認從0開始
		loadTreeData(parameter) //獲取數據
	})

點擊某個節點會根據節點的key對應的字段,獲取下級節點。並添加到節點數據中。

			let parameter = {} //查詢參數
			parameter[props.parentIdColumn] = treeNode[props.fieldNamesKey] //獲取當前節點的id
			const result = props.treeData(parameter) //調用父組件傳遞的方法
			if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
				result.then((data) => {
					setTimeout(() => {
						treeNode.dataRef[props.fieldNamesChildren] = data
						treeData.value = [...treeData.value]
						resolve()
					}, 500)
				})
			}

三、後端實現

以組織樹爲例,原來的tree方法需要增加父ID參數來根據父ID獲取下級節點

/// <summary>
/// 組織樹查詢參數
/// 懶加載用
/// </summary>
public class SysOrgTreeInput
{
    /// <summary>
    /// 父Id
    /// </summary>
    public long? ParentId { get; set; }
}

原來的tree方法也要改一改,如果選擇器ID不爲空則表示是懶加載,只加載子節點。


    /// <inheritdoc />
    public async Task<List<SysOrg>> Tree(List<long> orgIds = null, SysOrgTreeInput treeInput = null)
    {
        long parentId = SimpleAdminConst.Zero;//父級ID
        //獲取所有組織
        var sysOrgs = await GetListAsync();
        if (orgIds != null)
            sysOrgs = GetParentListByIds(sysOrgs, orgIds);//如果組織ID不爲空則獲取組織ID列表的所有父節點
        //如果選擇器ID不爲空則表示是懶加載,只加載子節點
        if (treeInput != null && treeInput.ParentId != null)
        {
            parentId = treeInput.ParentId.Value;
            sysOrgs = GetSysOrgChildenLazy(sysOrgs, treeInput.ParentId.Value);//獲取懶加載下級
        }
        sysOrgs = sysOrgs.OrderBy(it => it.SortCode).ToList();//排序
        //構建組織樹
        var result = ConstrucOrgTrees(sysOrgs, parentId);
        return result;
    }
GetSysOrgChildenLazy方法會去根據父ID找到對應的子節點並判斷子節點是否有下級節點。
    /// <summary>
    /// 獲取組織下級(懶加載)
    /// </summary>
    /// <param name="orgList"></param>
    /// <param name="parentId"></param>
    /// <returns></returns>
    public List<SysOrg> GetSysOrgChildenLazy(List<SysOrg> orgList, long parentId)
    {
        //找下級組織ID列表
        var orgs = orgList.Where(it => it.ParentId == parentId).ToList();
        if (orgs.Count > 0)//如果數量大於0
        {
            var data = new List<SysOrg>();
            foreach (var item in orgs)//遍歷組織
            {
                var childen = orgList.Where(it => it.ParentId == item.Id).ToList();//獲取子節點
                //遍歷子節點
                childen.ForEach(it =>
                {
                    if (!orgList.Any(org => org.ParentId == it.Id)) it.IsLeaf = true;//如果沒有下級,則設置爲葉子節點
                });
                data.AddRange(childen);//添加子節點);
                data.Add(item);//添加到列表
            }
            return data;//返回結果
        }
        return new List<SysOrg>();
    }

需要在組織實體中加個IsLeaf字段判斷是不是葉子節點,如果IsLeaf是true就表示沒有子節點了,前端樹控件也不會顯示小箭頭。


    /// <summary>
    /// 設置爲葉子節點(設置了loadData時有效)
    /// </summary>
    [SugarColumn(IsIgnore = true)]
    public bool? IsLeaf { get; set; }

四、效果

最後實現效果如下,這裏一次請求加載2級節點。

 

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