@@ -92,37 +92,52 @@ const VirtualList = Vue.component(NAME, {
9292 this . scrollToOffset ( 0 )
9393 } else if ( index >= this . dataSources . length - 1 ) {
9494 // scroll to bottom
95- this . scrollToOffset ( this . getScrollSize ( ) )
95+ this . scrollToBottom ( )
9696 } else {
9797 const offset = this . virtual . getOffset ( index )
9898 this . scrollToOffset ( offset )
9999 }
100100 } ,
101101
102+ // set current scroll position to bottom
103+ scrollToBottom ( ) {
104+ const { shepherd } = this . $refs
105+ if ( shepherd ) {
106+ shepherd . scrollIntoView ( false )
107+
108+ // check if it's really scrolled to the bottom
109+ // maybe list doesn't render and calculate to last range
110+ // so we need retry in next event loop until it really at bottom
111+ setTimeout ( ( ) => {
112+ if ( this . getOffset ( ) + this . getClientSize ( ) < this . getScrollSize ( ) ) {
113+ this . scrollToBottom ( )
114+ }
115+ } , 3 ) ;
116+ }
117+ } ,
118+
102119 // ----------- public method end -----------
103120
104121 getUniqueIdFromDataSources ( ) {
105122 return this . dataSources . map ( ( dataSource ) => dataSource [ this . dataKey ] )
106123 } ,
107124
108- // get client viewport size (width or height)
125+ // return current scroll offset
126+ getOffset ( ) {
127+ const { root } = this . $refs
128+ return root ? root [ this . directionKey ] : 0
129+ } ,
130+
131+ // return client viewport size (width or height)
109132 getClientSize ( ) {
110133 const { root } = this . $refs
111- if ( root ) {
112- return root [ this . isHorizontal ? 'clientWidth' : 'clientHeight' ]
113- } else {
114- return 0
115- }
134+ return root ? root [ this . isHorizontal ? 'clientWidth' : 'clientHeight' ] : 0
116135 } ,
117136
118- // get all scroll size (width or height)
137+ // return all scroll size (width or height)
119138 getScrollSize ( ) {
120139 const { root } = this . $refs
121- if ( root ) {
122- return root [ this . isHorizontal ? 'scrollWidth' : 'scrollHeight' ]
123- } else {
124- return 0
125- }
140+ return root ? root [ this . isHorizontal ? 'scrollWidth' : 'scrollHeight' ] : 0
126141 } ,
127142
128143 // event called when each item mounted or size changed
@@ -149,17 +164,12 @@ const VirtualList = Vue.component(NAME, {
149164 } ,
150165
151166 onScroll ( evt ) {
152- const { root } = this . $refs
153- if ( ! root ) {
154- return
155- }
156-
157- const offset = root [ this . directionKey ]
167+ const offset = this . getOffset ( )
158168 const clientSize = this . getClientSize ( )
159169 const scrollSize = this . getScrollSize ( )
160170
161171 // iOS scroll-spring-back behavior will make direction mistake
162- if ( offset + clientSize > scrollSize ) {
172+ if ( offset + clientSize > scrollSize || ! scrollSize ) {
163173 return
164174 }
165175
@@ -170,9 +180,9 @@ const VirtualList = Vue.component(NAME, {
170180 // emit event in special position
171181 emitEvent ( offset , clientSize , scrollSize , evt ) {
172182 const range = this . virtual . getRange ( )
173- if ( this . virtual . isFront ( ) && ! ! this . dataSources . length && offset - this . topThreshold <= 0 ) {
183+ if ( this . virtual . isFront ( ) && ! ! this . dataSources . length && ( offset - this . topThreshold <= 0 ) ) {
174184 this . $emit ( 'totop' , evt , range )
175- } else if ( this . virtual . isBehind ( ) && offset + clientSize + this . bottomThreshold >= scrollSize ) {
185+ } else if ( this . virtual . isBehind ( ) && ( offset + clientSize + this . bottomThreshold >= scrollSize ) ) {
176186 this . $emit ( 'tobottom' , evt , range )
177187 } else {
178188 this . $emit ( 'scroll' , evt , range )
@@ -250,7 +260,12 @@ const VirtualList = Vue.component(NAME, {
250260 event : EVENT_TYPE . SLOT ,
251261 uniqueKey : SLOT_TYPE . FOOTER
252262 }
253- } , footer ) : null
263+ } , footer ) : null ,
264+
265+ // an empty element use to scroll to bottom
266+ h ( 'div' , {
267+ ref : 'shepherd'
268+ } )
254269 ] )
255270 }
256271} )
0 commit comments