1
1
import type { PropType , Component , CSSProperties } from 'vue' ;
2
2
import {
3
+ onMounted ,
4
+ onUpdated ,
3
5
ref ,
4
6
defineComponent ,
5
7
watchEffect ,
@@ -155,12 +157,58 @@ const List = defineComponent({
155
157
null ,
156
158
) ;
157
159
158
- const calRes = ref < {
160
+ const calRes = reactive < {
159
161
scrollHeight ?: number ;
160
162
start ?: number ;
161
163
end ?: number ;
162
164
offset ?: number ;
163
- } > ( { } ) ;
165
+ } > ( {
166
+ scrollHeight : undefined ,
167
+ start : 0 ,
168
+ end : 0 ,
169
+ offset : undefined ,
170
+ } ) ;
171
+
172
+ const offsetHeight = ref ( 0 ) ;
173
+ onMounted ( ( ) => {
174
+ nextTick ( ( ) => {
175
+ offsetHeight . value = fillerInnerRef . value ?. offsetHeight || 0 ;
176
+ } ) ;
177
+ } ) ;
178
+ onUpdated ( ( ) => {
179
+ nextTick ( ( ) => {
180
+ offsetHeight . value = fillerInnerRef . value ?. offsetHeight || 0 ;
181
+ } ) ;
182
+ } ) ;
183
+ watch (
184
+ [ useVirtual , mergedData ] ,
185
+ ( ) => {
186
+ if ( ! useVirtual . value ) {
187
+ Object . assign ( calRes , {
188
+ scrollHeight : undefined ,
189
+ start : 0 ,
190
+ end : mergedData . value . length - 1 ,
191
+ offset : undefined ,
192
+ } ) ;
193
+ }
194
+ } ,
195
+ { immediate : true } ,
196
+ ) ;
197
+ watch (
198
+ [ useVirtual , mergedData , offsetHeight , inVirtual ] ,
199
+ ( ) => {
200
+ // Always use virtual scroll bar in avoid shaking
201
+ if ( useVirtual . value && ! inVirtual . value ) {
202
+ Object . assign ( calRes , {
203
+ scrollHeight : offsetHeight . value ,
204
+ start : 0 ,
205
+ end : mergedData . value . length - 1 ,
206
+ offset : undefined ,
207
+ } ) ;
208
+ }
209
+ } ,
210
+ { immediate : true } ,
211
+ ) ;
164
212
watch (
165
213
[
166
214
inVirtual ,
@@ -170,82 +218,73 @@ const List = defineComponent({
170
218
updatedMark ,
171
219
heights ,
172
220
( ) => props . height ,
221
+ offsetHeight ,
173
222
] ,
174
223
( ) => {
175
- setTimeout ( ( ) => {
176
- if ( ! useVirtual . value ) {
177
- calRes . value = {
178
- scrollHeight : undefined ,
179
- start : 0 ,
180
- end : mergedData . value . length - 1 ,
181
- offset : undefined ,
182
- } ;
183
- return ;
184
- }
224
+ if ( ! useVirtual . value || ! inVirtual . value ) {
225
+ return ;
226
+ }
227
+ if ( ! inVirtual . value ) {
228
+ Object . assign ( calRes , {
229
+ scrollHeight : offsetHeight . value ,
230
+ start : 0 ,
231
+ end : mergedData . value . length - 1 ,
232
+ offset : undefined ,
233
+ } ) ;
234
+ return ;
235
+ }
185
236
186
- // Always use virtual scroll bar in avoid shaking
187
- if ( ! inVirtual . value ) {
188
- calRes . value = {
189
- scrollHeight : fillerInnerRef . value ?. offsetHeight || 0 ,
190
- start : 0 ,
191
- end : mergedData . value . length - 1 ,
192
- offset : undefined ,
193
- } ;
194
- return ;
237
+ let itemTop = 0 ;
238
+ let startIndex : number | undefined ;
239
+ let startOffset : number | undefined ;
240
+ let endIndex : number | undefined ;
241
+ const dataLen = mergedData . value . length ;
242
+ const data = mergedData . value ;
243
+ for ( let i = 0 ; i < dataLen ; i += 1 ) {
244
+ const item = data [ i ] ;
245
+ const key = getKey ( item ) ;
246
+
247
+ const cacheHeight = heights . value [ key ] ;
248
+ const currentItemBottom =
249
+ itemTop + ( cacheHeight === undefined ? props . itemHeight ! : cacheHeight ) ;
250
+
251
+ if ( currentItemBottom >= state . scrollTop && startIndex === undefined ) {
252
+ startIndex = i ;
253
+ startOffset = itemTop ;
195
254
}
196
255
197
- let itemTop = 0 ;
198
- let startIndex : number | undefined ;
199
- let startOffset : number | undefined ;
200
- let endIndex : number | undefined ;
201
- const dataLen = mergedData . value . length ;
202
- const data = mergedData . value ;
203
- for ( let i = 0 ; i < dataLen ; i += 1 ) {
204
- const item = data [ i ] ;
205
- const key = getKey ( item ) ;
206
-
207
- const cacheHeight = heights . value [ key ] ;
208
- const currentItemBottom =
209
- itemTop + ( cacheHeight === undefined ? props . itemHeight ! : cacheHeight ) ;
210
-
211
- if ( currentItemBottom >= state . scrollTop && startIndex === undefined ) {
212
- startIndex = i ;
213
- startOffset = itemTop ;
214
- }
215
-
216
- // Check item bottom in the range. We will render additional one item for motion usage
217
- if ( currentItemBottom > state . scrollTop + props . height ! && endIndex === undefined ) {
218
- endIndex = i ;
219
- }
220
-
221
- itemTop = currentItemBottom ;
256
+ // Check item bottom in the range. We will render additional one item for motion usage
257
+ if ( currentItemBottom > state . scrollTop + props . height ! && endIndex === undefined ) {
258
+ endIndex = i ;
222
259
}
223
260
224
- // Fallback to normal if not match. This code should never reach
225
- /* istanbul ignore next */
226
- if ( startIndex === undefined ) {
227
- startIndex = 0 ;
228
- startOffset = 0 ;
229
- }
230
- if ( endIndex === undefined ) {
231
- endIndex = dataLen - 1 ;
232
- }
261
+ itemTop = currentItemBottom ;
262
+ }
263
+
264
+ // Fallback to normal if not match. This code should never reach
265
+ /* istanbul ignore next */
266
+ if ( startIndex === undefined ) {
267
+ startIndex = 0 ;
268
+ startOffset = 0 ;
269
+ }
270
+ if ( endIndex === undefined ) {
271
+ endIndex = dataLen - 1 ;
272
+ }
233
273
234
- // Give cache to improve scroll experience
235
- endIndex = Math . min ( endIndex + 1 , dataLen ) ;
236
- calRes . value = {
237
- scrollHeight : itemTop ,
238
- start : startIndex ,
239
- end : endIndex ,
240
- offset : startOffset ,
241
- } ;
274
+ // Give cache to improve scroll experience
275
+ endIndex = Math . min ( endIndex + 1 , dataLen ) ;
276
+ Object . assign ( calRes , {
277
+ scrollHeight : itemTop ,
278
+ start : startIndex ,
279
+ end : endIndex ,
280
+ offset : startOffset ,
242
281
} ) ;
243
282
} ,
244
- { immediate : true , flush : 'post' } ,
283
+ { immediate : true } ,
245
284
) ;
246
285
247
286
// =============================== In Range ===============================
248
- const maxScrollHeight = computed ( ( ) => calRes . value . scrollHeight ! - props . height ! ) ;
287
+ const maxScrollHeight = computed ( ( ) => calRes . scrollHeight ! - props . height ! ) ;
249
288
250
289
function keepInRange ( newScrollTop : number ) {
251
290
let newTop = newScrollTop ;
@@ -416,15 +455,6 @@ const List = defineComponent({
416
455
setInstance,
417
456
mergedData,
418
457
} = this ;
419
- const listChildren = renderChildren (
420
- mergedData ,
421
- start ,
422
- end ,
423
- setInstance ,
424
- children ,
425
- sharedConfig ,
426
- ) ;
427
-
428
458
return (
429
459
< div
430
460
style = { {
@@ -446,9 +476,11 @@ const List = defineComponent({
446
476
offset = { offset }
447
477
onInnerResize = { collectHeight }
448
478
ref = "fillerInnerRef"
449
- >
450
- { listChildren }
451
- </ Filler >
479
+ v-slots = { {
480
+ default : ( ) =>
481
+ renderChildren ( mergedData , start , end , setInstance , children , sharedConfig ) ,
482
+ } }
483
+ > </ Filler >
452
484
</ Component >
453
485
454
486
{ useVirtual && (
0 commit comments