-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0cc090e
commit d3dd00c
Showing
5 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { toTree } from './toTree'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { toTree } from './toTree'; | ||
|
||
describe('toTree', function () { | ||
it('should convert flat array to tree structure', function () { | ||
const flatArray = [ | ||
{ id: '1', parentId: '' }, | ||
{ id: '2', parentId: '1' }, | ||
{ id: '3', parentId: '1' }, | ||
{ id: '4', parentId: '2' }, | ||
{ id: '5', parentId: '' }, | ||
]; | ||
|
||
expect(toTree(flatArray)).toEqual([ | ||
{ | ||
id: '1', | ||
parentId: '', | ||
children: [ | ||
{ | ||
id: '2', | ||
parentId: '1', | ||
children: [{ id: '4', parentId: '2', children: [] }], | ||
}, | ||
{ id: '3', parentId: '1', children: [] }, | ||
], | ||
}, | ||
{ id: '5', parentId: '', children: [] }, | ||
]); | ||
}); | ||
|
||
it('should support custom rootId', () => { | ||
const flatArray = [ | ||
{ id: 1, parentId: 'root', name: 'Root 1' }, | ||
{ id: 2, parentId: 1, name: 'Child 1.1' }, | ||
]; | ||
|
||
const tree = toTree(flatArray, { rootId: 'root' }); | ||
|
||
expect(tree).toHaveLength(1); | ||
expect(tree[0].children).toHaveLength(1); | ||
}); | ||
|
||
it('should support data formatting', () => { | ||
const flatArray = [ | ||
{ id: 1, parentId: '', title: 'Root 1' }, | ||
{ id: 2, parentId: 1, title: 'Child 1.1' }, | ||
]; | ||
|
||
const format = (item: any) => ({ | ||
id: item.id, | ||
parentId: item.parentId, | ||
name: item.title, | ||
}); | ||
|
||
const tree = toTree(flatArray, { format }); | ||
|
||
expect(tree[0].name).toBe('Root 1'); | ||
expect(tree[0].children[0].name).toBe('Child 1.1'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import type { ITreeListItem, ITreeKey, IChildrenKey, ITree } from './types'; | ||
|
||
interface IToTreeProps { | ||
rootId?: ITreeKey; | ||
/** | ||
* 格式化数据为统一数据格式 | ||
* @param item | ||
* @returns | ||
*/ | ||
format?: (item: any) => ITreeListItem; | ||
} | ||
|
||
/** | ||
* 将数组转换为树结构 | ||
* @param list | ||
* @param opts | ||
* @returns | ||
*/ | ||
export function toTree<T extends IChildrenKey = 'children'>( | ||
list: any[] = [], | ||
opts: IToTreeProps = {}, | ||
): ITree<T> { | ||
const { rootId = '', format } = opts; | ||
|
||
if (!Array.isArray(list)) { | ||
throw new TypeError('Expected an array but got an invalid argument'); | ||
} | ||
|
||
const map = new Map<ITreeKey, ITreeListItem>(); | ||
const roots: any[] = []; | ||
|
||
// 构建节点的映射关系 | ||
list.forEach((item) => { | ||
const itemData = format ? format(item) : item; | ||
map.set(itemData.id, { ...itemData, children: [] }); | ||
}); | ||
|
||
// 构建树结构 | ||
list.forEach((item) => { | ||
const itemData = format ? format(item) : item; | ||
const node = map.get(itemData.id); | ||
|
||
if (itemData.parentId === rootId) { | ||
roots.push(node); | ||
} else if (map.get(itemData.parentId)) { | ||
map.get(itemData.parentId)!.children.push(node); | ||
} | ||
}); | ||
|
||
return roots as ITree<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export type ITreeKey = string | number; | ||
|
||
export type IChildrenKey = ITreeKey; | ||
|
||
export type ITree<T extends IChildrenKey = 'children'> = { | ||
[key in T]?: ITree<T>[]; | ||
} & { | ||
[key in ITreeKey]: any; | ||
}; | ||
|
||
export interface ITreeListItem { | ||
id: ITreeKey; | ||
parentId: ITreeKey; | ||
[key: string]: any; | ||
} | ||
|
||
const tree: ITree = [{ id: '', children: [] }]; |