一、说明
当有一个树形结构的数据有非常多个节点的时候,一次性加载所有节点会显得过于臃肿,可能会对性能造成影响,正好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级节点。
标签:SimpleAdmin,Tree,节点,Ant,sysOrgs,result,parameter,ID,加载 From: https://www.cnblogs.com/huguodong/p/17445872.html