Skip to content

Commit ecb5789

Browse files
committed
feat(core): arrayField add "getIndexKey" "getCurrentKeyIndex" method to optimize render performance
1 parent b995220 commit ecb5789

File tree

6 files changed

+49
-7
lines changed

6 files changed

+49
-7
lines changed

packages/core/src/models/ArrayField.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,22 @@ import { Field } from './Field'
99
import { Form } from './Form'
1010
import { JSXComponent, IFieldProps, FormPathPattern } from '../types'
1111

12+
const uniqueIdRef = { current: 0 }
13+
14+
const getUniqueId = () => {
15+
return uniqueIdRef.current++
16+
}
17+
18+
const createIndexKey = () => {
19+
return `_$id_${getUniqueId()}_`
20+
}
21+
1222
export class ArrayField<
1323
Decorator extends JSXComponent = any,
1424
Component extends JSXComponent = any
1525
> extends Field<Decorator, Component, any, any[]> {
1626
displayName = 'ArrayField'
27+
indexKeys: Array<string> = []
1728

1829
constructor(
1930
address: FormPathPattern,
@@ -22,6 +33,7 @@ export class ArrayField<
2233
designable: boolean
2334
) {
2435
super(address, props, form, designable)
36+
this.indexKeys = []
2537
this.makeAutoCleanable()
2638
}
2739

@@ -32,20 +44,37 @@ export class ArrayField<
3244
(newLength, oldLength) => {
3345
if (oldLength && !newLength) {
3446
cleanupArrayChildren(this, 0)
47+
this.indexKeys = []
3548
} else if (newLength < oldLength) {
3649
cleanupArrayChildren(this, newLength)
50+
this.indexKeys = this.indexKeys.slice(0, newLength)
3751
}
3852
}
3953
)
4054
)
4155
}
4256

57+
getIndexKey(index: number) {
58+
if (!this.indexKeys[index]) {
59+
const newKey = createIndexKey()
60+
this.indexKeys[index] = newKey
61+
return newKey
62+
}
63+
return this.indexKeys[index]
64+
}
65+
66+
getCurrentKeyIndex(key: string) {
67+
return this.indexKeys.indexOf(key)
68+
}
69+
4370
push = (...items: any[]) => {
4471
return action(() => {
4572
if (!isArr(this.value)) {
4673
this.value = []
74+
this.indexKeys = []
4775
}
4876
this.value.push(...items)
77+
this.indexKeys.push(...items.map(createIndexKey))
4978
return this.onInput(this.value)
5079
})
5180
}
@@ -59,6 +88,7 @@ export class ArrayField<
5988
deleteCount: 1,
6089
})
6190
this.value.pop()
91+
this.indexKeys.pop()
6292
return this.onInput(this.value)
6393
})
6494
}
@@ -67,6 +97,7 @@ export class ArrayField<
6797
return action(() => {
6898
if (!isArr(this.value)) {
6999
this.value = []
100+
this.indexKeys = []
70101
}
71102
if (items.length === 0) {
72103
return
@@ -76,6 +107,7 @@ export class ArrayField<
76107
insertCount: items.length,
77108
})
78109
this.value.splice(index, 0, ...items)
110+
this.indexKeys.splice(index, 0, ...items.map(createIndexKey))
79111
return this.onInput(this.value)
80112
})
81113
}
@@ -88,6 +120,7 @@ export class ArrayField<
88120
deleteCount: 1,
89121
})
90122
this.value.splice(index, 1)
123+
this.indexKeys.splice(index, 1)
91124
return this.onInput(this.value)
92125
})
93126
}
@@ -100,6 +133,7 @@ export class ArrayField<
100133
deleteCount: 1,
101134
})
102135
this.value.shift()
136+
this.indexKeys.shift()
103137
return this.onInput(this.value)
104138
})
105139
}
@@ -114,6 +148,7 @@ export class ArrayField<
114148
insertCount: items.length,
115149
})
116150
this.value.unshift(...items)
151+
this.indexKeys.unshift(...items.map(createIndexKey))
117152
return this.onInput(this.value)
118153
})
119154
}
@@ -123,6 +158,7 @@ export class ArrayField<
123158
if (fromIndex === toIndex) return
124159
return action(() => {
125160
move(this.value, fromIndex, toIndex)
161+
move(this.indexKeys, fromIndex, toIndex)
126162
exchangeArrayState(this, {
127163
fromIndex,
128164
toIndex,

packages/react/docs/api/components/ArrayField.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ const ArrayComponent = observer(() => {
4040
<>
4141
<div>
4242
{field.value?.map((item, index) => (
43-
<div key={index} style={{ display: 'flex-block', marginBottom: 10 }}>
43+
<div
44+
key={field.getIndexKey(index)}
45+
style={{ display: 'flex-block', marginBottom: 10 }}
46+
>
4447
<Space>
4548
<Field name={index} component={[Input]} />
4649
<Button
@@ -105,7 +108,7 @@ export default () => (
105108
<div>
106109
{field.value?.map((item, index) => (
107110
<div
108-
key={index}
111+
key={field.getIndexKey(index)}
109112
style={{ display: 'flex-block', marginBottom: 10 }}
110113
>
111114
<Space>

packages/react/docs/api/components/ArrayField.zh-CN.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ const ArrayComponent = observer(() => {
4040
<>
4141
<div>
4242
{field.value?.map((item, index) => (
43-
<div key={index} style={{ display: 'flex-block', marginBottom: 10 }}>
43+
<div
44+
key={field.getIndexKey(index)}
45+
style={{ display: 'flex-block', marginBottom: 10 }}
46+
>
4447
<Space>
4548
<Field name={index} component={[Input]} />
4649
<Button
@@ -105,7 +108,7 @@ export default () => (
105108
<div>
106109
{field.value?.map((item, index) => (
107110
<div
108-
key={index}
111+
key={field.getIndexKey(index)}
109112
style={{ display: 'flex-block', marginBottom: 10 }}
110113
>
111114
<Space>

packages/react/docs/api/components/RecursionField.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const ArrayItems = observer((props) => {
9797
<div>
9898
{props.value?.map((item, index) => {
9999
return (
100-
<div key={index} style={{ marginBottom: 10 }}>
100+
<div key={field.getIndexKey(index)} style={{ marginBottom: 10 }}>
101101
<Space>
102102
<RecursionField schema={schema.items} name={index} />
103103
<Button

packages/react/docs/api/components/RecursionField.zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const ArrayItems = observer((props) => {
9797
<div>
9898
{props.value?.map((item, index) => {
9999
return (
100-
<div key={index} style={{ marginBottom: 10 }}>
100+
<div key={field.getIndexKey(index)} style={{ marginBottom: 10 }}>
101101
<Space>
102102
<RecursionField schema={schema.items} name={index} />
103103
<Button

packages/vue/docs/demos/api/components/array-field.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<template #default="{ field }">
55
<div
66
v-for="(item, index) in field.value || []"
7-
:key="`${item.id}-${index}`"
7+
:key="field.getIndexKey(index)"
88
:style="{ marginBottom: '10px' }"
99
>
1010
<Space>

0 commit comments

Comments
 (0)