Angular中如何将JSON数据转换为适配PrimeNG TreeNode接口的树形结构
多级权限数据转PrimeNG TreeNode树形结构解决方案
问题背景
需要将API返回的多级权限数据转换为适配PrimeNG TreeNode接口的树形结构,现有实现仅支持父节点和一级子节点,无法处理二级及以上层级的子节点。
PrimeNG TreeNode接口定义
export interface TreeNode { label?: string; data?: any; icon?: any; expandedIcon?: any; collapsedIcon?: any; children?: TreeNode[]; leaf?: boolean; expanded?: boolean; type?: string; parent?: TreeNode; partialSelected?: boolean; styleClass?: string; draggable?: boolean; droppable?: boolean; selectable?: boolean; key?: string; }
API返回数据格式
"result": [ { "permissionName": "Roles", "level": 2, "selectable": true, "children": [ { "permissionName": "Roles.Create", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Roles.Edit", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Roles.Delete", "level": 3, "selectable": true, "children": [] } ] }, { "permissionName": "Users", "level": 2, "selectable": true, "children": [ { "permissionName": "Users.Create", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Users.Edit", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Users.Delete", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Users.ChangePermissions", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Users.Impersonation", "level": 3, "selectable": true, "children": [] }, { "permissionName": "Users.Unlock", "level": 3, "selectable": true, "children": [] } ] } ]
现有问题代码
let permissionResult = resultFromAPI; // let childrenArray: TreeNode[] = []; for(var i= 0; i< permissionResult.permissions.length;i++){ this.treeData.push({ label:permissionResult.permissions[i].permissionName, icon: 'pi pi-folder', data:permissionResult.permissions[i].permissionName, children: this.childrenArrayfunction(permissionResult.permissions[i].children) }) if (permissionResult.permissions[i].selected) { this.grantedPermissionNames.push(permissionResult.permissions[i].permissionName) } } childrenArrayfunction(resultArray:any[]=[]){ let childArray: TreeNode[]=[]; if(resultArray.length > 0){ for(var j= 0; j< resultArray.length;j++){ childArray.push({ label:resultArray[j].permissionName, data:resultArray[j].permissionName, icon: 'pi pi-folder', }) } } return childArray; }
上述代码仅处理一级子节点,未递归处理子节点的子节点,无法支持多级树形结构。
解决方案:递归转换函数
使用递归函数处理树形结构,可适配任意层级的权限数据转换:
核心转换函数
import { TreeNode } from 'primeng/api'; // 递归转换单个权限节点为TreeNode convertPermissionToTreeNode(permission: any): TreeNode { // 映射基础属性 const treeNode: TreeNode = { label: permission.permissionName, data: permission.permissionName, icon: 'pi pi-folder', selectable: permission.selectable, leaf: permission.children.length === 0 // 无子节点标记为叶子节点 }; // 递归处理子节点 if (permission.children && permission.children.length > 0) { treeNode.children = permission.children.map(child => this.convertPermissionToTreeNode(child)); } return treeNode; } // 批量转换权限列表为TreeNode数组 convertPermissionsToTreeNodes(permissions: any[]): TreeNode[] { return permissions.map(permission => this.convertPermissionToTreeNode(permission)); }
使用方式
let permissionResult = resultFromAPI; // 转换整个权限列表为树形结构 this.treeData = this.convertPermissionsToTreeNodes(permissionResult.permissions); // 递归收集所有选中的权限名称(如果需要) this.grantedPermissionNames = []; permissionResult.permissions.forEach(permission => { this.collectSelectedPermissions(permission); }); // 递归收集选中权限的辅助函数 collectSelectedPermissions(permission: any) { if (permission.selected) { this.grantedPermissionNames.push(permission.permissionName); } // 递归处理子节点的选中状态 if (permission.children && permission.children.length > 0) { permission.children.forEach(child => this.collectSelectedPermissions(child)); } }
方案说明
- 递归函数
convertPermissionToTreeNode会处理当前节点的属性映射,并对每个子节点重复调用自身,实现任意层级的转换。 - 通过
leaf属性标记叶子节点,优化PrimeNG树组件的渲染逻辑。 - 同步实现了递归收集选中权限的逻辑,确保所有层级的选中权限都能被正确收集。
内容的提问来源于stack exchange,提问作者ckeedee
相关产品推荐
相关产品推荐

