@@ -92,37 +92,52 @@ const VirtualList = Vue.component(NAME, {
92
92
this . scrollToOffset ( 0 )
93
93
} else if ( index >= this . dataSources . length - 1 ) {
94
94
// scroll to bottom
95
- this . scrollToOffset ( this . getScrollSize ( ) )
95
+ this . scrollToBottom ( )
96
96
} else {
97
97
const offset = this . virtual . getOffset ( index )
98
98
this . scrollToOffset ( offset )
99
99
}
100
100
} ,
101
101
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
+
102
119
// ----------- public method end -----------
103
120
104
121
getUniqueIdFromDataSources ( ) {
105
122
return this . dataSources . map ( ( dataSource ) => dataSource [ this . dataKey ] )
106
123
} ,
107
124
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)
109
132
getClientSize ( ) {
110
133
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
116
135
} ,
117
136
118
- // get all scroll size (width or height)
137
+ // return all scroll size (width or height)
119
138
getScrollSize ( ) {
120
139
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
126
141
} ,
127
142
128
143
// event called when each item mounted or size changed
@@ -149,17 +164,12 @@ const VirtualList = Vue.component(NAME, {
149
164
} ,
150
165
151
166
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 ( )
158
168
const clientSize = this . getClientSize ( )
159
169
const scrollSize = this . getScrollSize ( )
160
170
161
171
// iOS scroll-spring-back behavior will make direction mistake
162
- if ( offset + clientSize > scrollSize ) {
172
+ if ( offset + clientSize > scrollSize || ! scrollSize ) {
163
173
return
164
174
}
165
175
@@ -170,9 +180,9 @@ const VirtualList = Vue.component(NAME, {
170
180
// emit event in special position
171
181
emitEvent ( offset , clientSize , scrollSize , evt ) {
172
182
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 ) ) {
174
184
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 ) ) {
176
186
this . $emit ( 'tobottom' , evt , range )
177
187
} else {
178
188
this . $emit ( 'scroll' , evt , range )
@@ -250,7 +260,12 @@ const VirtualList = Vue.component(NAME, {
250
260
event : EVENT_TYPE . SLOT ,
251
261
uniqueKey : SLOT_TYPE . FOOTER
252
262
}
253
- } , footer ) : null
263
+ } , footer ) : null ,
264
+
265
+ // an empty element use to scroll to bottom
266
+ h ( 'div' , {
267
+ ref : 'shepherd'
268
+ } )
254
269
] )
255
270
}
256
271
} )
0 commit comments