[TypeScript] 将一个列表转为树形列表的函数(通用型)

今天分享一个自己实现的基于 TypeScript 的将列表转为树形列表的通用函数。

  /**
   * 将一个列表转化为树形列表, 列表数据需要本身支持转化成数型
   * @param list 列表数据
   * @param equalLevalItem 判断两个列表项是否同级且不相等的回调函数
   * @param listFirstIsRoot 使用列表中的第1项作为树的root节点
   * @param isRootItem 判断列表项是否为root节点的回调函数,listFirstIsRoot = false 时有效
   * @param childrenField 列表项中,存放 children 列表的字段名称
   * @param childrenMust 子列表字段是否必须存在,为 true 时,如果没有子列表,会将其设置为 []
   * @param item 当前列表项, 调用者传 undefined
   * @returns
   */
  // eslint-disable-next-line max-params
  static toTreeList<T>(
    list?: T[],
    equalLevalItem?: (a: T | undefined, item: T) => boolean,
    listFirstIsRoot: boolean = true,
    isRootItem?: (e: T, index: number) => boolean,
    childrenField: string = "children",
    childrenMust: boolean = false,
    item?: T,
  ): T[] {
    const children: T[] = []
    if (! list || list.length === 0) {
      return children
    }
    const handleChildren = (e: T) => {
      let srcData = e[childrenField];
      if (childrenMust && ! srcData) {
        srcData = []
        e[childrenField] = srcData
      }
      const data: T[] | undefined = srcData ? srcData as T[] : []
      data.push(...this.toTreeList(list, equalLevalItem, listFirstIsRoot, undefined, childrenField, childrenMust, e))
      if (! srcData && data.length > 0) {
        e[childrenField] = data;
      } else if (data.length === 0 && ! childrenMust) {
        e[childrenField] = undefined
      }
    }
    let v = item
    if (v === undefined) {
      if (listFirstIsRoot) {
        v = list[0]
        if (v[childrenField] === undefined) {
          v[childrenField].children = []
        }
        handleChildren(v)
        children.push(v)
      } else {
        // 找出 root 项
        list.forEach((e, index) => {
          if (isRootItem?.(e, index)) {
            handleChildren(e)
            children.push(e)
          }
        })
      }
      return children
    }
    list.filter((e) => {
      if (equalLevalItem?.(item, e)) { return e } // 排除掉当前 item
    }).forEach((e) => {
      handleChildren(e)
      children.push(e)
    })
    return children
  }

使用示例:

Utils.toTreeList(
      list,
      (src, item) => src?.id === item.pid && src.id !== item.id,
      false,
      (item, idx) => item.pid === 0
)
posted @ 2021-11-15 17:44  我爱我家喵喵  阅读(164)  评论(0编辑  收藏  举报