@@ -15,8 +15,8 @@ import {
15
15
forEach ,
16
16
inRange ,
17
17
} from '@tool-pack/basic' ;
18
+ import { useForwardRef , getClasses , useWatch } from '@pkg/shared' ;
18
19
import type { VirtualListProps } from './virtual-list.types' ;
19
- import { useForwardRef , getClasses } from '@pkg/shared' ;
20
20
import type { RequiredPart } from '@tool-pack/types' ;
21
21
22
22
const cls = getClasses ( 'virtual-list' , [ 'items' , 'wrapper' , 'item' ] , [ ] ) ;
@@ -25,6 +25,7 @@ const defaultProps = {
25
25
} satisfies Partial < VirtualListProps > ;
26
26
27
27
type Offsets = [ start : number , end : number ] ;
28
+ const offsetIndex = 2 ;
28
29
29
30
export const VirtualList : React . FC < VirtualListProps > = React . forwardRef <
30
31
HTMLElement ,
@@ -41,7 +42,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
41
42
42
43
const firstItemHeightRef = useRef ( 0 ) ;
43
44
const itemMapRef = useRef <
44
- Array < { isPreset : boolean ; height : number ; top : number } >
45
+ Array < { /* isPreset: boolean;*/ height : number ; top : number } >
45
46
> ( [ ] ) ;
46
47
const containerItemsLenRef = useRef ( 0 ) ;
47
48
const translateYRef = useRef ( 0 ) ;
@@ -67,9 +68,17 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
67
68
} ) ;
68
69
} , [ childList , offsets ] ) ;
69
70
70
- useEffect ( ( ) => {
71
+ useWatch ( childList . length , ( len ) => {
72
+ const old = autoFillLayoutRef . current ;
71
73
autoFillLayoutRef . current = true ;
72
- } , [ childList . length ] ) ;
74
+ if ( old || ! itemMapRef . current . length || len >= itemMapRef . current . length )
75
+ return ;
76
+
77
+ // 从 children 数量多到 children 数量少的情况
78
+ itemMapRef . current . length = 0 ;
79
+ // rootElRef.current?.dispatchEvent(new Event('scroll'));
80
+ setSafeOffsets ( 0 , 0 ) ;
81
+ } ) ;
73
82
74
83
useEffect ( ( ) => {
75
84
if ( ! autoFillLayoutRef . current ) return ;
@@ -94,7 +103,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
94
103
const { offsetHeight, offsetTop } = v ;
95
104
itemMapRef . current [ i ] = {
96
105
height : offsetHeight ,
97
- isPreset : false ,
106
+ // isPreset: false,
98
107
top : offsetTop ,
99
108
} ;
100
109
} ,
@@ -109,7 +118,7 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
109
118
itemMapRef . current [ index ] = {
110
119
height : firstItemHeightRef . current ,
111
120
top : prev . height + prev . top ,
112
- isPreset : true ,
121
+ // isPreset: true,
113
122
} ;
114
123
} ) ;
115
124
@@ -140,26 +149,27 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
140
149
const attr = el . getAttribute ( 'data-index' ) ;
141
150
const index = Number ( attr ) ;
142
151
const obj = itemMap [ index ] ;
143
- if ( obj ?. isPreset === false ) return ;
152
+ // if (obj?.isPreset === false) return;
144
153
const prev = itemMap [ index - 1 ] || defItem ;
145
154
const h = obj ?. height || firstItemHeightRef . current ;
146
155
const { offsetHeight } = el ;
147
156
itemMap [ index ] = {
148
157
top : prev . top + prev . height ,
149
158
height : offsetHeight ,
150
- isPreset : false ,
159
+ // isPreset: false,
151
160
} ;
152
161
if ( h !== offsetHeight ) {
153
162
isResized = true ;
154
163
lastIndex = index ;
155
164
}
156
165
} ) ;
157
166
167
+ // 如果某一个元素高度变化了,就需要把它后面的元素的 top 刷新一遍
158
168
if ( isResized ) {
159
169
const len = itemMap . length ;
160
170
for ( let i = lastIndex + 1 ; i < len ; i ++ ) {
161
171
const v = itemMap [ i ] ! ;
162
- // 跟新后续的 top
172
+ // 更新后续的 top
163
173
const prev = itemMap [ i - 1 ] || defItem ;
164
174
v . top = prev . top + prev . height ;
165
175
}
@@ -221,7 +231,6 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
221
231
}
222
232
}
223
233
224
- const offsetIndex = 2 ;
225
234
offsets [ 0 ] -= offsetIndex ;
226
235
offsets [ 1 ] += offsetIndex ;
227
236
return offsets ;
@@ -230,7 +239,10 @@ export const VirtualList: React.FC<VirtualListProps> = React.forwardRef<
230
239
const maxIndex = childList . length ;
231
240
start = getSafeNum ( start , 0 , maxIndex ) ;
232
241
end = getSafeNum ( end , 0 , maxIndex ) ;
233
- translateYRef . current = itemMapRef . current [ start ] ! . top ;
242
+
243
+ const im = itemMapRef . current [ start ] ;
244
+ if ( im ) translateYRef . current = im . top ;
245
+
234
246
setOffsets ( [ start , end ] ) ;
235
247
}
236
248
} ) ;
0 commit comments