export class TreeUtil> { map: {[k: string]: number} = {}; roots: T[] = []; /** * @field status * @type * 0 - 未成功执行 `config` 方法; * 1 - 已成功执行 `config` 方法; */ status: 0 | 1 = 0; pIdField!: keyof T; childIdField!: keyof T; levelIdField!: keyof T; constructor() {} /** * @function config - 配置字段名称 * @param pIdField - parent id 对应的字段 * @param childIdField - 节点 id 对应的字段 * @param levelIdField - 节点 level 对应的字段 * @example * ``` ts * T = { * pId: 0, * id: 1 * } * ``` * 则 `pIdField` 值为 ‘pId’, `childIdField` 的值为 1 */ config(pIdField: any, childIdField: any, levelIdField?: any): this { this.pIdField = pIdField; this.childIdField = childIdField; this.levelIdField = levelIdField; this.status = 1; return this; } /** * @function toTree * @param list - 源数据 * @param isSorted 是否是已根据 level 排序(祖先节点在前)的数据 * @description * 如果是已排序数据,则合并两次循环 * @link https://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript/22072374 */ toTree(list: T[], isSorted = false): T[] { if (this.status === 0) { throw new Error('Please execute config method first!'); } // list.sort((a, b) => (a[this.levelIdField] as any) - b[this.levelIdField]); if (isSorted) { list.forEach((node, index) => { this.initMap(node, index); this.addChildNode(this.roots, list, node); }); } else { list.forEach(this.initMap.bind(this)); list.forEach((node, index) => { this.addChildNode(this.roots, list, node); }); } return JSON.parse(JSON.stringify(this.roots)); } initMap(node: T, index: number): void { this.map[node.id] = index; node.children = []; } addChildNode(target: T[], sources: T[],childNode: T): void { if (childNode[this.pIdField] !== 0) { sources[this.map[childNode.pId]].children.push(childNode); } else { target.push(childNode); } } } interface TreeNode { [k: string]: any; children: U[]; }