【kk-utils】树结构工具——tree

前言

kk-utils 是一款我自己基于这几年开发封装出来的前端工具库

tree

treekk-utils里的工具之一(1.1.0版本开始支持),其作用是有多个针对树结构的方法函数,是我在写项目时积累下来的,几乎可以覆盖日常所需

当然,初始的代码是借鉴GitHubnewarea0大佬的代码,基于此源码的基础上进行修改和新增适合我业务的功能

使用方法

安装

js 复制代码
npm install kk-utils-library -S
pnpm add kk-utils-library -S

基础配置项

绝大部分函数的基础配置项都有以下选项可用

strategy

设置搜索策略,默认策略为pre

pre:深度优先,正序搜索

post:深度优先,反序搜索

breadth:广度优先

js 复制代码
import { filter } from 'kk-utils-library/tree';
const result = filter(tree, node => node.id > 2, { strategy: 'post' })

childrenKey

自定义子节点key名,默认值为children

js 复制代码
import { filter } from 'kk-utils-library/tree';
const result = filter(tree, node => node.id > 2, { childrenKey: 'items' })

getChildrenKey

设置一棵树上多种自定义子节点key

js 复制代码
const getChildrenKeyTree = [
  {
    key: '1',
    children: [
      {
        key: '2',
        subItems: [
          {
            key: '3'
          }
        ]
      }
    ]
  },
  {
    key: '4'
  }
];
const getChildrenKeyResult = filter(
  getChildrenKeyTree,
  (node) => node.id > 2,
  {
    getChildrenKey: (tree, meta) => {
      if (meta.depth === 1) {
        return 'subItems';
      }
    }
  }
);

可用方法

forEach

遍历树形数组/对象,对每个节点执行回调

js 复制代码
forEach(tree, callback, [options])
  • tree:树形数组/对象
  • callback:回调函数,对每个节点执行回调
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { forEach } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 111
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
forEach(data, (node) => {
  console.log(node.key);
});
// 1
// 11
// 111
// 112
// 12
// 122
// 1221
// 1222

filter

遍历树形数组/对象,并把返回非真值的节点剔除(不会影响原结构,返回的树是新生成的)

js 复制代码
filter(tree, callback, [options])
  • tree:树形数组/对象
  • callback:回调函数,对每个节点执行回调
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { filter } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 99
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = filter(data, (node) => node.key < 100);
console.log('result', result);
// {
//   "key": 1,
//   "children": [
//     {
//       "key": 11,
//       "children": [
//         {
//           "key": 99
//         }
//       ]
//     },
//     {
//       "key": 12,
//       "children": []
//     }
//   ]
// }

conditionsFilter

遍历树形数组/对象,并把返回非真值的节点剔除

这个方法和上面的filter的区别在于:

  • conditionsFilter不支持基础配置项
  • conditionsFilter在父级为true,而子级没数据的时候,可以选择携带出下一级的数据或者所有下级数据,这在比如区域列表过滤的时候,可以通过搜索省级带出所有市级或者所有子区域
  • conditionsFilter在能搜索匹配到最后一级的时候,并不会携带出兄弟节点
  • conditionsFilter支持函数过滤和对象/数组结构的值匹配过滤,但是值匹配过滤并不是全等,而是包含关系
js 复制代码
conditionsFilter(tree, conditions, [options])
  • tree:树形数组
  • conditions:过滤条件,
    • 可以为函数(item) => boolean
    • 也可以为对象{ name: '名称搜索', code: '编码搜索' },多个条件是&&的关系,必须都满足
  • options:配置项,可选,对象类型,不支持基础配置项
    • childrenKey:自定义子节点key名,默认值为children
    • withChildren:子级没数据的时候是否携带子级数据返回,默认值为true
    • allChildren:是否返回所有子级数据,默认值为false
js 复制代码
import { conditionsFilter } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 99
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = conditionsFilter(data, (node) => node.key === 122);
console.log('result', result);
// [
//   {
//     key: 1,
//     children: [
//       {
//         key: 12,
//         children: [
//           {
//             key: 122,
//             children: [
//               {
//                 key: 1221
//               },
//               {
//                 key: 1222
//               }
//             ]
//           }
//         ]
//       }
//     ]
//   }
// ];

map

遍历树形数组/对象,根据返回的对象,组成新的树

js 复制代码
map(tree, callback, [options])
  • tree:树形数组/对象
  • callback:每次迭代调用的函数,需要返回一个对象,返回的对象上无需包括子节点
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { map } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 111
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = map(data, (node) => ({ name: `No.${node.key}` }));
console.log('result', result);
// {
//   "name": "No.1",
//   "children": [
//     {
//       "name": "No.11",
//       "children": [
//         { "name": "No.111" },
//         { "name": "No.112" }
//       ]
//     },
//     {
//       "name": "No.12",
//       "children": [
//         {
//           "name": "No.122",
//           "children": [
//             { "name": "No.1221" },
//             { "name": "No.1222" }
//           ]
//         }
//       ]
//     }
//   ]
// }

find

遍历树形数组/对象,找到第一个返回非空值的节点

js 复制代码
find(tree, callback, [options])
  • tree:树形数组/对象
  • callback:每次迭代调用的函数,需要返回一个对象,返回的对象上无需包括子节点
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { find } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 111
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = find(data, (node) => node.key < 100 && node.key > 10);
console.log('result', result);
// {
//     "key": 11,
//     "children": [
//         {
//             "key": 111
//         },
//         {
//             "key": 112
//         }
//     ]
// }

some

遍历树形数组/对象,判断是否存在符合条件的节点

js 复制代码
some(tree, callback, [options])
  • tree:树形数组/对象
  • callback:每次迭代调用的函数,需要返回一个对象,返回的对象上无需包括子节点
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { some } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 111
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = some(data, (node) => node.key < 100 && node.key > 10);
console.log('result', result);
// true

toArray

将树形数组/对象转换为一维数组,数组会包含所有节点

js 复制代码
toArray(tree, [options])
  • tree:树形数组/对象
  • options:配置项,可选,对象类型,支持基础配置项
    • leafKey:叶子节点的key,默认为isLeaf
    • withChildren:是否携带子级数据,默认为false
js 复制代码
import { toArray } from 'kk-utils-library/tree';

const data = [
  {
    key: '1',
    children: [
      {
        key: '2',
        children: [
          {
            key: '3'
          }
        ]
      }
    ]
  }
];
const result = toArray(data);
console.log('result', result);
// [
//   {
//     key: '1',
//     isLeaf: false
//   },
//   {
//     key: '2',
//     isLeaf: false
//   },
//   {
//     key: '3',
//     isLeaf: true
//   }
// ];

fromArray

将数组转换为树形数组/对象

js 复制代码
fromArray(array, [options])
  • array:数组
  • options:配置项,可选,对象类型,不支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
    • parentKey:自定义父节点key名,默认值为parentId
js 复制代码
import { fromArray } from 'kk-utils-library/tree';

const data = [
  {
    id: '1',
    name: '1'
  },
  {
    id: '2',
    name: '2',
    parentId: '1'
  },
  {
    id: '3',
    name: '3',
    parentId: '1'
  },
  {
    id: '4',
    name: '4',
    parentId: '2'
  },
  {
    id: '5',
    name: '5'
  }
];
const result = fromArray(data);
console.log('result', result);
// [
//   {
//     id: '1',
//     name: '1',
//     children: [
//       {
//         id: '2',
//         name: '2',
//         parentId: '1',
//         children: [
//           {
//             id: '4',
//             name: '4',
//             parentId: '2'
//           }
//         ]
//       },
//       {
//         id: '3',
//         name: '3',
//         parentId: '1'
//       }
//     ]
//   },
//   {
//     id: '5',
//     name: '5'
//   }
// ];

toTree

将数组转换为树形数组

这个方法和上面的fromArray的区别在于:

  • toTree支持root顶层标识配置
  • toTree支持levelKey节点层级key配置
  • toTree支持leafKey叶子节点key配置
js 复制代码
toTree(tree, conditions, [options])
  • tree:树形数组
  • conditions:过滤条件,
    • 可以为函数(item) => boolean
    • 也可以为对象{ name: '名称搜索', code: '编码搜索' },多个条件是&&的关系,必须都满足
  • options:配置项,可选,对象类型,不支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
    • parentKey:自定义父节点key名,默认值为parentId
    • root:顶层标识配置
    • levelKey:节点层级key配置
    • leafKey:叶子节点key配置
js 复制代码
import { toTree } from 'kk-utils-library/tree';

const data = [
  {
    id: '1',
    name: '1'
  },
  {
    id: '2',
    name: '2',
    parentId: '1'
  },
  {
    id: '3',
    name: '3',
    parentId: '1'
  },
  {
    id: '4',
    name: '4',
    parentId: '2'
  },
  {
    id: '5',
    name: '5'
  }
];
const result = toTree(data);
console.log('result', result);
// [
//   {
//     id: '1',
//     name: '1',
//     children: [
//       {
//         id: '2',
//         name: '2',
//         parentId: '1',
//         children: [
//           {
//             id: '4',
//             name: '4',
//             parentId: '2',
//             children: null,
//             level: 3,
//             isLeaf: true
//           }
//         ],
//         level: 2,
//         isLeaf: false
//       },
//       {
//         id: '3',
//         name: '3',
//         parentId: '1',
//         children: null,
//         level: 2,
//         isLeaf: true
//       }
//     ],
//     level: 1,
//     isLeaf: false
//   },
//   {
//     id: '5',
//     name: '5',
//     children: null,
//     level: 1,
//     isLeaf: true
//   }
// ];

getDepthAndLength

获取树结构的深度和最长子级长度

js 复制代码
getDepthAndLength(tree, [options])
  • tree:树形数组
  • options:配置项,可选,对象类型,支持基础配置项
js 复制代码
import { getDepthAndLength } from 'kk-utils-library/tree';

const data = [
  {
    key: 1,
    children: [
      {
        key: 11,
        children: [
          {
            key: 99
          },
          {
            key: 112
          }
        ]
      },
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = getDepthAndLength(data);
console.log('result', result);
// { "depth": 3, "length": 2 } // 深度和最长子级数量

fixParentId

给树形数组每一项补上parentId

js 复制代码
fixParentId(array, [options])
  • array:数组
  • options:配置项,可选,对象类型,不支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
    • parentKey:自定义父节点key名,默认值为parentId
js 复制代码
import { fixParentId } from 'kk-utils-library/tree';

const data = [
  {
    id: 1,
    children: [
      {
        id: 11,
        children: [
          {
            id: 99
          },
          {
            id: 112
          }
        ]
      },
      {
        id: 12,
        children: [
          {
            id: 122,
            children: [
              {
                id: 1221
              },
              {
                id: 1222
              }
            ]
          }
        ]
      }
    ]
  }
];
const result = fixParentId(data);
console.log('result', result);
// [
//   {
//     id: 1,
//     children: [
//       {
//         id: 11,
//         children: [
//           {
//             id: 99,
//             parentId: 11
//           },
//           {
//             id: 112,
//             parentId: 11
//           }
//         ],
//         parentId: 1
//       },
//       {
//         id: 12,
//         children: [
//           {
//             id: 122,
//             children: [
//               {
//                 id: 1221,
//                 parentId: 122
//               },
//               {
//                 id: 1222,
//                 parentId: 122
//               }
//             ],
//             parentId: 12
//           }
//         ],
//         parentId: 1
//       }
//     ]
//   }
// ];

findAncestor

从树形数组里根据传入的节点ID查找出它的所有祖先元素,返回一个有层级关系的tree数据

js 复制代码
findAncestor(array, [options])
  • array:数组
  • options:配置项,可选,对象类型,不支持基础配置项
    • root顶层标识配置
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
    • parentKey:自定义父节点key名,默认值为parentId
    • withChildren:是否携带子级数据,默认为false
js 复制代码
import { findAncestor } from 'kk-utils-library/tree';

const data = [
  {
    id: 1,
    children: [
      {
        id: 11,
        children: [
          {
            id: 99,
            parentId: 11
          },
          {
            id: 112,
            parentId: 11
          }
        ],
        parentId: 1
      },
      {
        id: 12,
        children: [
          {
            id: 122,
            children: [
              {
                id: 1221,
                parentId: 122
              },
              {
                id: 1222,
                parentId: 122
              }
            ],
            parentId: 12
          }
        ],
        parentId: 1
      }
    ]
  }
];
const result = findAncestor(data, 1221);
console.log('result', result);
// {
//   id: 1,
//   children: [
//     {
//       id: 12,
//       children: [
//         {
//           id: 122,
//           children: [
//             {
//               id: 1221,
//               parentId: 122
//             }
//           ],
//           parentId: 12
//         }
//       ],
//       parentId: 1
//     }
//   ]
// }
相关推荐
风中飘爻31 分钟前
JavaScript:BOM编程
开发语言·javascript·ecmascript
恋猫de小郭33 分钟前
Android Studio Cloud 正式上线,不只是 Android,随时随地改 bug
android·前端·flutter
清岚_lxn5 小时前
原生SSE实现AI智能问答+Vue3前端打字机流效果
前端·javascript·人工智能·vue·ai问答
ZoeLandia5 小时前
Element UI 设置 el-table-column 宽度 width 为百分比无效
前端·ui·element-ui
橘子味的冰淇淋~6 小时前
解决 vite.config.ts 引入scss 预处理报错
前端·vue·scss
萌萌哒草头将军7 小时前
💎这么做,cursor 生成的代码更懂你!💎
javascript·visual studio code·cursor
小小小小宇8 小时前
V8 引擎垃圾回收机制详解
前端
lauo8 小时前
智体知识库:ai-docs对分布式智体编程语言Poplang和javascript的语法的比较(知识库问答)
开发语言·前端·javascript·分布式·机器人·开源
拉不动的猪8 小时前
设计模式之------单例模式
前端·javascript·面试
一袋米扛几楼989 小时前
【React框架】什么是 Vite?如何使用vite自动生成react的目录?
前端·react.js·前端框架