UNPKG

@diyaner/ding

Version:

dingiyan常用ts/js工具

257 lines 9.21 kB
"use strict"; /* * @copyright: ChengXuan * @Author: ding * @Date: 2022-08-13 09:23:13 * @LastEditors: ding * @LastEditTime: 2022-09-12 11:39:30 * @Description: file content */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TreeNode = exports.ListToTree = void 0; class ListToTree { constructor( /** origin list */ originlist) { /** * in passing transacted to obj when to tree. * * the options.id is key. */ this.obj = {}; this.checkTheOriginList(originlist); this.list = [...originlist]; } /** 静态方法,实例化一个listToTree,并返回实例 */ static init(originList) { return new ListToTree(originList); } setOption(opt) { this.option = opt; } getOption() { return this.option; } /** * the main method. do turn list to tree. */ toTree(option) { option && this.setOption(option); this.checkParams(); this.option.allowEmptyChildren = this.option.allowEmptyChildren === false ? false : true; /** 实现思路:先把列表按parent和id进行key value展平成对象 */ const parentField = this.option.parent; const idField = this.option.id; const rootValue = this.option.rootValue || 0; const sortFunction = this.option.sort; /** 以父级id为key的对象 值为子元素列表 */ const objp = {}; /** 以节点id为key的对象 值为元素对象 */ const objId = {}; for (const item of this.list) { const parentId = item[parentField]; objp[parentId] = objp[parentId] || []; objp[parentId].push(item); objId[item[idField]] = item; } /** 根节点列表 */ const rootList = objp[rootValue] || []; // 处理父id不存在的情况,改为将root作为父id 这样可以拿到断层的游离节点放入根位置 if (this.option.absentParentResetToRootValue) { const ids = Object.keys(objId); const pids = Object.keys(objp); for (const pid of pids) { if (ids.includes(pid) || pid.toString() === rootValue.toString()) continue; rootList.push(...objp[pid]); } } if (!rootList.length) throw new Error(`rootValue ${rootValue} could not find node.`); const tree = []; const objNode = {}; /** 递归遍历 */ const recursion = (arr, isRoot) => { if (sortFunction) { arr = sortFunction(arr); } if (isRoot) { for (const item of arr) { this.option.itemHandler && this.option.itemHandler(item, undefined); const nodeItem = new TreeNode(item, this.option); objNode[nodeItem.id] = nodeItem; tree.push(nodeItem); nodeItem.level = 0; nodeItem.parentIds = []; // top level's parent is empty. nodeItem.parentNode = null; if (objp[nodeItem.id]) { recursion(objp[nodeItem.id], false); } } } else { for (const item of arr) { const parentItem = objNode[item[parentField]]; this.option.itemHandler && this.option.itemHandler(item, parentItem); const nodeItem = new TreeNode(item, this.option); objNode[nodeItem.id] = nodeItem; parentItem.children = !!parentItem.children ? parentItem.children : []; parentItem.children.push(nodeItem); nodeItem.level = parentItem.level + 1; nodeItem.parentIds = [nodeItem.parent, ...parentItem.parentIds]; nodeItem.parentNode = parentItem; if (objp[nodeItem.id]) { recursion(objp[nodeItem.id], false); } } } }; recursion(rootList, true); this.obj = objNode; this.tree = tree; return tree; } /** * get one node's level. * * top level is 0 * */ getLevel(id) { const treeNode = this.obj[id]; if (treeNode == undefined) { throw new Error(`your id is not found node object.`); } return treeNode.level; } /** get node's parents node id. */ getParentIds(id) { const arr = this.obj[id]; if (arr == undefined) { throw new Error(`your id ${id} cound not found on node object.`); } return arr.parentIds; } /** get all parents node object. */ getParentNodes(id) { const arr = this.getParentIds(id); return arr.map((nodeId) => this.obj[nodeId]); } getNode(id) { const obj = this.obj[id]; if (obj == undefined) { throw new Error(`your id ${id} cound not found on node object.`); } return obj; } /** 获取一个节点的所有后代子节点id列表 */ getAllChildrens(id) { const result = Object.keys(this.obj).filter((item) => { return this.obj[item].parentIds.includes(id); }); return result; } /** remove one or multiple node by id */ removeNode(id) { const idFieldName = this.option.id; const removeIds = Array.isArray(id) ? id : [id]; const newList = this.list.filter((item) => !removeIds.includes(item[idFieldName])); this.list = newList; return this.toTree(this.option); } pushNode(obj) { this.list.push(obj); return this.toTree(this.option); } /** 检查源数据列表 */ checkTheOriginList(list) { if (!Array.isArray(list)) { throw new Error(`[${ListToTree.name}] the argument [list] require array.`); } } /** 检查toTree的选项参数 */ checkParams() { if (!this.option) { throw new Error(`[${ListToTree.name}] the [option] is require.`); } this.checkTheOriginList(this.list); if (!this.option.id || !["string", "number"].includes(typeof this.option.id)) { throw new Error(`[${ListToTree.name}] the argument [option] require id field and it's must be stringNumber or number.`); } if (!this.option.parent || !["string", "number"].includes(typeof this.option.parent)) { throw new Error(`[${ListToTree.name}] the argument [option] require parent field and it's must be stringNumber or number.`); } } } exports.ListToTree = ListToTree; exports.default = ListToTree; /** 树节点类 */ class TreeNode { constructor(obj, option) { /** 节点层级 */ this.level = 0; /** 父节点id的数组 从父级一直到顶层 */ this.parentIds = []; this.origin = obj; this.option = option; this.children = this.option.allowEmptyChildren ? [] : undefined; } /** node label 从源对象中映射 */ get label() { return this.origin[this.option.mapToLabel || "label"]; } /** node id 从源对象中映射 */ get id() { return this.origin[this.option.id || "id"]; } /** node value 从源对象映射,使用自定义map映射或id的映射 */ get value() { return this.origin[this.option.mapToValue || this.option.id || "id"]; } /** node parent id 从源对象中映射 的父节点id */ get parent() { return this.origin[this.option.parent || "parent"]; } /** 获取所有后代节点的id列表 */ getAllChildrensId() { if (!this.children || this.children.length === 0) return []; const sonIds = []; const afterSonIds = []; for (const child of this.children) { sonIds.push(child.id); afterSonIds.push(...child.getAllChildrensId()); } return [...sonIds, ...afterSonIds]; } /** 获取所有后代节点对象 */ getAllChildrensNode() { if (!this.children || this.children.length === 0) return []; const sonNodes = []; const afterSonNodes = []; for (const child of this.children) { sonNodes.push(child); afterSonNodes.push(...child.getAllChildrensNode()); } return [...sonNodes, ...afterSonNodes]; } /** 用于json序列化,去除循环引用,获取get属性 */ toJSON() { const obj = { id: this.id, value: this.value, parent: this.parent, label: this.label, level: this.level, parentIds: this.parentIds, origin: this.origin, children: this.children, }; if (!this.option.treeNodeToJson) return obj; const res = this.option.treeNodeToJson(obj, this); return res; } } exports.TreeNode = TreeNode; //# sourceMappingURL=listToTree.js.map