您的当前位置:首页正文

前端JS中常用的处理树型结构的常用工具函数

来源:化拓教育网
前端JS中常⽤的处理树型结构的常⽤⼯具函数

使⽤了lodash的深拷贝⽅法

import { cloneDeep } from 'lodash-es'

/**

* 遍历 tree

* @param {object[]} tree

* @param {function} cb - 回调函数

* @param {string} children - ⼦节点 字段名

* @param {string} mode - 遍历模式,DFS:深度优先遍历 BFS:⼴度优先遍历 * @return {void} Do not return anything */

export function treeForEach(tree: any[], cb: (item: any) => unknown, children = 'children', mode = 'DFS'): void { if (!Array.isArray(tree)) {

throw new TypeError('tree is not an array') }

if (typeof children !== 'string') {

throw new TypeError('children is not a string') }

if (children === '') {

throw new Error('children is not a valid string') }

// 深度优先遍历 depth first search function DFS(treeData: any[]) { // eslint-disable-next-line for (const item of treeData) { cb(item)

if (Array.isArray(item[children])) { DFS(item[children]) } } }

// ⼴度优先遍历 breadth first search function BFS(treeData: any[]) { const queen = treeData while (queen.length > 0) { const item = queen.shift() cb(item)

if (Array.isArray(item[children])) { queen.push(...item[children]) } } }

if (mode === 'BFS') { BFS(tree) } else { DFS(tree) }}

/**

* tree 转 数组

* @param {object[]} tree

* @param {string} children - ⼦节点 字段名

* @param {string} mode - 遍历模式,DFS:深度优先遍历 BFS:⼴度优先遍历 * @return {array} */

export function treeToList(tree: Array, children = 'children', mode = 'DFS'): Array { if (!Array.isArray(tree)) {

throw new TypeError('tree is not an array') }

if (typeof children !== 'string') {

throw new TypeError('children is not a string') }

if (children === '') {

throw new Error('children is not a valid string') }

tree = cloneDeep(tree) const list: any = []

treeForEach(tree, (item : any) => { list.push(item)

}, children, mode)

list.forEach((item: any) => {

delete item[children] // 会改变 原数据 }) return list}

/**

* 数组 转 tree

* @param {object[]} list * @param {object} options

* @param {string|number|null|undefined} options.rootID - 根节点ID * @param {string|number} options.id - 唯⼀标识 字段名 * @param {string|number} options.pid - ⽗节点ID 字段名 * @param {string} options.children - ⼦节点 字段名 * @return {array} */

interface Options { rootID?: string, id?: string, pid?: string, children?: string}

export function listToTree(list: any[], options:Options): Array { const {

rootID = null, // 根节点ID,pid === rootID 即为 ⼀级节点 id = 'id', // 唯⼀标识

pid = 'pid', // ⽗节点ID 字段

children = 'children' // ⼦节点 字段 } = options || {}

if (!Array.isArray(list)) {

throw new TypeError('list is not an array') }

if (typeof children !== 'string') {

throw new TypeError('children is not a string') }

if (children === '') {

throw new Error('children is not a valid string') }

list = cloneDeep(list)

const tree: any = []

const map = list.reduce((res, item) => { res.set(item[id], item) return res }, new Map())

Array.from(map.keys()).forEach(key => { const node = map.get(key)

if (node[pid] === rootID) { // ⼀级节点,直接添加到 tree tree.push(node)

} else { // ⾮⼀级节点,查找⽗级,并添加到⽗级 children 中 const pNode = map.get(node[pid]) if (Array.isArray(pNode[children])) { pNode[children].push(node) } else {

pNode[children] = [node] } } }) return tree}

因篇幅问题不能全部显示,请点此查看更多更全内容