Skip to content

Commit

Permalink
feat(cloneDeep,TreeData): 支持 ignore
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Jan 3, 2021
1 parent 9f6e7b4 commit f9bb684
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 11 deletions.
17 changes: 17 additions & 0 deletions src/utils/TreeData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,23 @@ describe('TreeData', () => {
).toMatchSnapshot()
})

test('cloneIgnore', () => {
const x = { x: 1 }
expect(
new TreeData(
[
{
x,
},
],
{
cloneIgnore: value =>
typeof value === 'object' && (value as any).x === 1,
},
).export()[0].x,
).toBe(x)
})

// test('大数据', () => {
// const data = range(0, 1000).map(i => ({
// id: `${i}`,
Expand Down
24 changes: 20 additions & 4 deletions src/utils/TreeData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ export interface TreeDataOptions<TNode extends TreeDataNode> {
* @default 'DFS'
*/
searchStrategy?: TreeDataSearchStrategy

/**
* 克隆数据时忽略的值。
*/
cloneIgnore?: (value: unknown) => boolean | undefined
}

export interface TreeDataTraverseFnPayload<TNode extends TreeDataNode> {
Expand Down Expand Up @@ -92,6 +97,8 @@ export class TreeData<TNode extends TreeDataNode> {

private searchStrategy: TreeDataSearchStrategy

private cloneIgnore: ((value: unknown) => boolean | undefined) | undefined

/**
* 构造函数。
*
Expand All @@ -102,11 +109,16 @@ export class TreeData<TNode extends TreeDataNode> {
data: TreeDataSingleRootData<TNode> | TreeDataMultipleRootData<TNode>,
options: TreeDataOptions<TNode> = {},
) {
this.data = cloneDeepFast(Array.isArray(data) ? data : [data])
this.cloneIgnore = options?.cloneIgnore
this.data = this.cloneDeep(Array.isArray(data) ? data : [data])
this.childrenPropName = options?.childrenPropName || ('children' as any)
this.searchStrategy = options?.searchStrategy || 'DFS'
}

private cloneDeep<T>(value: T): T {
return cloneDeepFast(value, this.cloneIgnore)
}

/**
* 核心遍历函数。
*/
Expand Down Expand Up @@ -560,7 +572,7 @@ export class TreeData<TNode extends TreeDataNode> {
* 导出数据。
*/
export(): TreeDataData<TNode> {
return cloneDeepFast(this.data)
return this.cloneDeep(this.data)
}

/**
Expand All @@ -571,7 +583,7 @@ export class TreeData<TNode extends TreeDataNode> {
this.traverse(payload => {
list.push(payload.node)
})
return cloneDeepFast(list)
return this.cloneDeep(list)
}

/**
Expand All @@ -585,8 +597,12 @@ export class TreeData<TNode extends TreeDataNode> {
list: TItem[],
idKey: keyof TItem,
parentIdKey: keyof TItem,
cloneIgnore?: TreeDataOptions<TItem>['cloneIgnore'],
): TreeData<TreeDataStandardNode<TItem>> {
const _list: Array<TreeDataStandardNode<TItem>> = cloneDeepFast(list) as any
const _list: Array<TreeDataStandardNode<TItem>> = cloneDeepFast(
list,
cloneIgnore,
) as any
const data = _list
.map(item => {
item.children = _list.filter(
Expand Down
18 changes: 11 additions & 7 deletions src/utils/cloneDeepFast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,48 @@
* 深克隆快速版。
*
* @param value 要克隆的值
* @param ignore 忽略的值
* @returns 返回克隆后的值
* @example
* ```typescript
* cloneDeepFast({ x: [1] })
* // => { x: [1] }
* ```
*/
export function cloneDeepFast<T>(value: T): T {
export function cloneDeepFast<T>(
value: T,
ignore?: (value: unknown) => boolean | undefined,
): T {
if (typeof value !== 'object' || value === null) return value
if (value instanceof Date) return new Date(value)
if (Array.isArray(value)) return cloneArray(value)
if (Array.isArray(value)) return cloneArray(value, ignore)
const o2 = {}
for (const k in value) {
if (Object.hasOwnProperty.call(value, k) === false) continue
const cur = value[k]
if (typeof cur !== 'object' || cur === null) {
if (typeof cur !== 'object' || cur === null || (ignore && ignore(cur))) {
o2[k] = cur
} else if (cur instanceof Date) {
o2[k] = new Date(cur)
} else {
o2[k] = cloneDeepFast(cur)
o2[k] = cloneDeepFast(cur, ignore)
}
}
return o2
}

function cloneArray(a) {
function cloneArray(a, ignore) {
const keys = Object.keys(a)
const a2 = new Array(keys.length)
for (let i = 0; i < keys.length; i++) {
const k = keys[i]
const cur = a[k]
if (typeof cur !== 'object' || cur === null) {
if (typeof cur !== 'object' || cur === null || (ignore && ignore(cur))) {
a2[k] = cur
} else if (cur instanceof Date) {
a2[k] = new Date(cur)
} else {
a2[k] = cloneDeepFast(cur)
a2[k] = cloneDeepFast(cur, ignore)
}
}
return a2
Expand Down

0 comments on commit f9bb684

Please sign in to comment.