11import type { PropType , Component , CSSProperties } from 'vue' ;
22import {
3+ onMounted ,
4+ onUpdated ,
35 ref ,
46 defineComponent ,
57 watchEffect ,
@@ -155,12 +157,58 @@ const List = defineComponent({
155157 null ,
156158 ) ;
157159
158- const calRes = ref < {
160+ const calRes = reactive < {
159161 scrollHeight ?: number ;
160162 start ?: number ;
161163 end ?: number ;
162164 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+ ) ;
164212 watch (
165213 [
166214 inVirtual ,
@@ -170,82 +218,73 @@ const List = defineComponent({
170218 updatedMark ,
171219 heights ,
172220 ( ) => props . height ,
221+ offsetHeight ,
173222 ] ,
174223 ( ) => {
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+ }
185236
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 ;
195254 }
196255
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 ;
222259 }
223260
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+ }
233273
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 ,
242281 } ) ;
243282 } ,
244- { immediate : true , flush : 'post' } ,
283+ { immediate : true } ,
245284 ) ;
246285
247286 // =============================== In Range ===============================
248- const maxScrollHeight = computed ( ( ) => calRes . value . scrollHeight ! - props . height ! ) ;
287+ const maxScrollHeight = computed ( ( ) => calRes . scrollHeight ! - props . height ! ) ;
249288
250289 function keepInRange ( newScrollTop : number ) {
251290 let newTop = newScrollTop ;
@@ -416,15 +455,6 @@ const List = defineComponent({
416455 setInstance,
417456 mergedData,
418457 } = this ;
419- const listChildren = renderChildren (
420- mergedData ,
421- start ,
422- end ,
423- setInstance ,
424- children ,
425- sharedConfig ,
426- ) ;
427-
428458 return (
429459 < div
430460 style = { {
@@ -446,9 +476,11 @@ const List = defineComponent({
446476 offset = { offset }
447477 onInnerResize = { collectHeight }
448478 ref = "fillerInnerRef"
449- >
450- { listChildren }
451- </ Filler >
479+ v-slots = { {
480+ default : ( ) =>
481+ renderChildren ( mergedData , start , end , setInstance , children , sharedConfig ) ,
482+ } }
483+ > </ Filler >
452484 </ Component >
453485
454486 { useVirtual && (
0 commit comments