7
7
getRangeIndex ,
8
8
getItemTop ,
9
9
GHOST_ITEM_KEY ,
10
- OriginValues ,
11
- TargetValues ,
12
- getSimilarity ,
13
10
} from './util' ;
14
11
15
12
type RenderFunc < T > = ( item : T ) => React . ReactNode ;
@@ -151,20 +148,27 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
151
148
} ) ;
152
149
153
150
// We use the item before removed item as base compare position to enhance the accuracy
154
- const compareItemIndex = removedItemIndex - 1 ;
155
- const compareItemKey = this . getItemKey ( compareItemIndex , prevProps ) ;
156
-
157
151
const { startIndex : originStartIndex , itemIndex : originItemIndex } = this . state ;
158
- let compareItemTop = this . state . startItemTop ;
152
+
153
+ let originCompareItemIndex = removedItemIndex - 1 ;
154
+ if ( originCompareItemIndex >= originItemIndex ) originCompareItemIndex = originItemIndex ;
155
+ const compareItemKey = this . getItemKey ( originCompareItemIndex , prevProps ) ;
156
+
157
+ let originCompareItemTop = this . state . startItemTop ;
159
158
for ( let index = originStartIndex ; index <= originItemIndex ; index += 1 ) {
160
159
const key = this . getItemKey ( index , prevProps ) ;
161
160
if ( key === compareItemKey ) {
162
161
break ;
163
162
}
164
163
165
- compareItemTop += this . itemElementHeights [ key ] || 0 ;
164
+ originCompareItemTop += this . itemElementHeights [ key ] || 0 ;
166
165
}
167
166
167
+ // Find current compare item index
168
+ const compareItemIndex = dataSource . findIndex (
169
+ ( _ , index ) => this . getItemKey ( index ) === compareItemKey ,
170
+ ) ;
171
+
168
172
// Loop to generate compared item top and find best one
169
173
const { scrollHeight, clientHeight } = this . listRef . current ;
170
174
const maxScrollTop = scrollHeight - clientHeight ;
@@ -186,47 +190,65 @@ class List<T> extends React.Component<ListProps<T>, ListState> {
186
190
visibleCount ,
187
191
) ;
188
192
189
- let locatedItemTop = getItemTop ( {
190
- itemIndex,
191
- itemOffsetPtg,
192
- itemElementHeights : this . itemElementHeights ,
193
- scrollTop : this . listRef . current . scrollTop ,
194
- scrollPtg,
195
- clientHeight : this . listRef . current . clientHeight ,
196
- getItemKey : this . getItemKey ,
197
- } ) ;
198
-
199
- let newCompareItemTop : number = null ;
200
- for ( let index = itemIndex ; index >= startIndex ; index -= 1 ) {
201
- const key = this . getItemKey ( index ) ;
202
- if ( key === compareItemKey ) {
203
- newCompareItemTop = locatedItemTop ;
204
- break ;
205
- }
193
+ /**
194
+ * No need to check if compare item out of the index
195
+ * to save performance.
196
+ */
197
+ if ( startIndex <= compareItemIndex && compareItemIndex <= endIndex ) {
198
+ let locatedItemTop = getItemTop ( {
199
+ itemIndex,
200
+ itemOffsetPtg,
201
+ itemElementHeights : this . itemElementHeights ,
202
+ scrollTop : this . listRef . current . scrollTop ,
203
+ scrollPtg,
204
+ clientHeight : this . listRef . current . clientHeight ,
205
+ getItemKey : this . getItemKey ,
206
+ } ) ;
206
207
207
- if ( index <= 0 ) {
208
- break ;
208
+ let newCompareItemTop : number = null ;
209
+ if ( compareItemIndex <= itemIndex ) {
210
+ // Measure if compare item is before located item
211
+ for ( let index = itemIndex ; index >= startIndex ; index -= 1 ) {
212
+ const key = this . getItemKey ( index ) ;
213
+ if ( key === compareItemKey ) {
214
+ newCompareItemTop = locatedItemTop ;
215
+ break ;
216
+ }
217
+
218
+ if ( index <= 0 ) {
219
+ break ;
220
+ }
221
+
222
+ const prevItemKey = this . getItemKey ( index - 1 ) ;
223
+ locatedItemTop -= this . itemElementHeights [ prevItemKey ] || 0 ;
224
+ }
225
+ } else {
226
+ // Measure if compare item is after located item
227
+ for ( let index = itemIndex ; index <= endIndex ; index += 1 ) {
228
+ const key = this . getItemKey ( index ) ;
229
+ locatedItemTop += this . itemElementHeights [ key ] || 0 ;
230
+ if ( key === compareItemKey ) {
231
+ newCompareItemTop = locatedItemTop ;
232
+ break ;
233
+ }
234
+ }
209
235
}
210
236
211
- const prevItemKey = this . getItemKey ( index - 1 ) ;
212
- locatedItemTop -= this . itemElementHeights [ prevItemKey ] || 0 ;
213
- }
214
-
215
- if ( newCompareItemTop !== null ) {
216
- const similarity = Math . abs ( newCompareItemTop - compareItemTop ) ;
217
- if ( similarity < bestSimilarity ) {
218
- bestScrollTop = scrollTop ;
219
- bestSimilarity = similarity ;
220
- bestItemIndex = itemIndex ;
221
- bestItemOffsetPtg = itemOffsetPtg ;
222
- bestStartIndex = startIndex ;
223
- bestEndIndex = endIndex ;
237
+ if ( newCompareItemTop !== null ) {
238
+ const similarity = Math . abs ( newCompareItemTop - originCompareItemTop ) ;
239
+ if ( similarity < bestSimilarity ) {
240
+ bestScrollTop = scrollTop ;
241
+ bestSimilarity = similarity ;
242
+ bestItemIndex = itemIndex ;
243
+ bestItemOffsetPtg = itemOffsetPtg ;
244
+ bestStartIndex = startIndex ;
245
+ bestEndIndex = endIndex ;
246
+ }
224
247
}
225
248
}
226
249
}
227
250
228
251
// Update `scrollTop` to new calculated position
229
- console . log ( 'DONE:' , bestScrollTop ) ;
230
252
if ( bestScrollTop !== null ) {
231
253
this . lockScroll = true ;
232
254
this . listRef . current . scrollTop = bestScrollTop ;
0 commit comments