|
59 | 59 | end: start + keeps, // end index. |
60 | 60 | keeps: keeps, // nums keeping in real dom. |
61 | 61 | total: 0, // all items count, update in render filter. |
62 | | - offset: 0, // cache scrollTop offset. |
| 62 | + offset: 0, // cache current scroll offset. |
| 63 | + offsetAll: 0, // cache all the scroll offset. |
63 | 64 | direct: 'd', // cache scroll direction. |
64 | | - fireTime: 0, // cache last event fire time avoid compact. |
65 | 65 | paddingTop: 0, // container wrapper real padding-top. |
66 | 66 | paddingBottom: 0, // container wrapper real padding-bottom. |
67 | 67 | varCache: {}, // cache variable index height and padding offset. |
|
70 | 70 | } |
71 | 71 | }, |
72 | 72 |
|
73 | | - mounted: function () { |
74 | | - if (this.start) { |
75 | | - var start = this.getZone(this.start).start |
76 | | - this.setScrollTop(this.variable ? this.getVarOffset(start) : start * this.size) |
77 | | - } |
78 | | - }, |
79 | | - |
80 | 73 | watch: { |
81 | | - start: function () { |
82 | | - this.alter = 'start' |
83 | | - }, |
84 | 74 | remain: function () { |
85 | 75 | this.alter = 'remain' |
86 | 76 | }, |
| 77 | + size: function () { |
| 78 | + this.alter = 'size' |
| 79 | + }, |
87 | 80 | bench: function () { |
88 | 81 | this.alter = 'bench' |
| 82 | + }, |
| 83 | + start: function () { |
| 84 | + this.alter = 'start' |
89 | 85 | } |
90 | 86 | }, |
91 | 87 |
|
|
105 | 101 | this.updateZone(offset) |
106 | 102 | } |
107 | 103 |
|
| 104 | + if (offset >= delta.offsetAll) { |
| 105 | + this.triggerEvent('tobottom') |
| 106 | + } |
| 107 | + |
108 | 108 | if (this.onscroll) { |
109 | 109 | this.onscroll(e, { |
110 | 110 | end: delta.end, |
|
128 | 128 | var bench = this.bench || this.remain |
129 | 129 |
|
130 | 130 | // for better performance, if scroll pass items within now bench, do not update. |
131 | | - if (!zone.overflow && (overs > delta.start) && (overs - delta.start <= bench)) { |
| 131 | + if (!zone.isLast && (overs > delta.start) && (overs - delta.start <= bench)) { |
132 | 132 | return |
133 | 133 | } |
134 | 134 |
|
|
139 | 139 |
|
140 | 140 | // return the scroll passed items count in variable height. |
141 | 141 | getVarOvers: function (offset) { |
142 | | - var delta = this.delta |
143 | 142 | var low = 0 |
144 | 143 | var middle = 0 |
145 | 144 | var middleOffset = 0 |
| 145 | + var delta = this.delta |
146 | 146 | var high = delta.total |
147 | 147 |
|
148 | 148 | while (low <= high) { |
149 | 149 | middle = low + Math.floor((high - low) / 2) |
150 | 150 | middleOffset = this.getVarOffset(middle) |
151 | 151 |
|
152 | | - // calculate the variable average size at first binary search. |
| 152 | + // calculate the average variable size at first binary search. |
153 | 153 | if (!delta.varAverSize) { |
154 | 154 | delta.varAverSize = Math.floor(middleOffset / middle) |
155 | 155 | } |
|
171 | 171 | var delta = this.delta |
172 | 172 | var cache = delta.varCache[index] |
173 | 173 |
|
174 | | - if (cache && !nocache) { |
| 174 | + if (!nocache && cache) { |
175 | 175 | return cache.offset |
176 | 176 | } |
177 | 177 |
|
|
217 | 217 | } |
218 | 218 | }, |
219 | 219 |
|
220 | | - // the ONLY ONE public method, let the parent to update variable by index. |
221 | | - updateVariable: function (index) { |
222 | | - // update all the offfsets ahead of index. |
223 | | - this.getVarOffset(index, true) |
224 | | - }, |
225 | | - |
226 | | - // avoid overflow range. |
227 | | - isOverflow: function (start) { |
| 220 | + // retun the variable all heights use to judge reach to bottom. |
| 221 | + getVarAllHeight: function () { |
228 | 222 | var delta = this.delta |
229 | | - var overflow = (delta.total > delta.keeps && start + this.remain >= delta.total) || (start >= delta.total) |
230 | | - if (overflow && delta.direct === 'd') { |
231 | | - this.triggerEvent('tobottom') |
| 223 | + if (delta.total - delta.end <= delta.keeps || delta.varLastCalcIndex === delta.total - 1) { |
| 224 | + return this.getVarOffset(delta.total) |
| 225 | + } else { |
| 226 | + return this.getVarOffset(delta.start) + (delta.total - delta.end) * (delta.varAverSize || this.size) |
232 | 227 | } |
233 | | - return overflow |
234 | 228 | }, |
235 | 229 |
|
236 | | - // trigger a props event on parent. |
237 | | - triggerEvent: function (event) { |
238 | | - var now = +new Date() |
239 | | - var delta = this.delta |
240 | | - if (this[event] && now - delta.fireTime > 30) { |
241 | | - this[event]() |
242 | | - delta.fireTime = now |
243 | | - } |
| 230 | + // the ONLY ONE public method, let the parent to update variable by index. |
| 231 | + updateVariable: function (index) { |
| 232 | + // update all the offfsets ahead of index. |
| 233 | + this.getVarOffset(index, true) |
244 | 234 | }, |
245 | 235 |
|
246 | 236 | // return the right zone info base on `start/index`. |
|
251 | 241 | index = parseInt(index, 10) |
252 | 242 | index = index < 0 ? 0 : index |
253 | 243 |
|
254 | | - var overflow = this.isOverflow(index) |
255 | | - // if overflow range return the last zone. |
256 | | - if (overflow) { |
| 244 | + var lastStart = delta.total - delta.keeps |
| 245 | + var isLast = (index <= delta.total && index >= lastStart) || (index > delta.total) |
| 246 | + if (isLast) { |
257 | 247 | end = delta.total |
258 | | - start = Math.max(0, delta.total - delta.keeps) |
| 248 | + start = Math.max(0, lastStart) |
259 | 249 | } else { |
260 | 250 | start = index |
261 | 251 | end = start + delta.keeps |
|
264 | 254 | return { |
265 | 255 | end: end, |
266 | 256 | start: start, |
267 | | - overflow: overflow |
| 257 | + isLast: isLast |
| 258 | + } |
| 259 | + }, |
| 260 | + |
| 261 | + // trigger a props event on parent. |
| 262 | + triggerEvent: function (event) { |
| 263 | + if (this[event]) { |
| 264 | + this[event]() |
268 | 265 | } |
269 | 266 | }, |
270 | 267 |
|
|
285 | 282 |
|
286 | 283 | delta.total = slots.length |
287 | 284 |
|
288 | | - var paddingTop, paddingBottom |
289 | | - var hasPadding = slots.length > delta.keeps |
| 285 | + var paddingTop, paddingBottom, allHeight |
| 286 | + var hasPadding = delta.total > delta.keeps |
290 | 287 |
|
291 | 288 | if (this.variable) { |
| 289 | + allHeight = this.getVarAllHeight() |
292 | 290 | paddingTop = hasPadding ? this.getVarPaddingTop() : 0 |
293 | 291 | paddingBottom = hasPadding ? this.getVarPaddingBottom() : 0 |
294 | 292 | } else { |
| 293 | + allHeight = this.size * delta.total |
295 | 294 | paddingTop = this.size * (hasPadding ? delta.start : 0) |
296 | | - paddingBottom = this.size * (hasPadding ? slots.length - delta.keeps : 0) - paddingTop |
| 295 | + paddingBottom = this.size * (hasPadding ? delta.total - delta.keeps : 0) - paddingTop |
297 | 296 | } |
298 | 297 |
|
299 | 298 | delta.paddingTop = paddingTop |
300 | 299 | delta.paddingBottom = paddingBottom |
| 300 | + delta.offsetAll = allHeight - this.size * this.remain |
301 | 301 |
|
302 | 302 | return slots.filter(function (slot, index) { |
303 | 303 | return index >= delta.start && index <= delta.end |
304 | 304 | }) |
305 | 305 | } |
306 | 306 | }, |
307 | 307 |
|
308 | | - // update delta and zone when prorps change. |
| 308 | + mounted: function () { |
| 309 | + if (this.start) { |
| 310 | + var start = this.getZone(this.start).start |
| 311 | + this.setScrollTop(this.variable ? this.getVarOffset(start) : start * this.size) |
| 312 | + } |
| 313 | + }, |
| 314 | + |
| 315 | + // check if delta should update when prorps change. |
309 | 316 | beforeUpdate: function () { |
310 | 317 | var delta = this.delta |
311 | 318 | delta.keeps = this.remain + (this.bench || this.remain) |
|
314 | 321 | var oldStart = alterStart ? this.start : delta.start |
315 | 322 | var zone = this.getZone(oldStart) |
316 | 323 |
|
317 | | - // if changing start, update scroll position after update. |
| 324 | + // if start change, update scroll position. |
318 | 325 | if (alterStart) { |
319 | 326 | this.$nextTick(this.setScrollTop.bind(this, this.variable |
320 | | - ? this.getVarOffset(zone.overflow ? delta.total : zone.start) |
321 | | - : zone.overflow ? delta.total * this.size : zone.start * this.size) |
| 327 | + ? this.getVarOffset(zone.isLast ? delta.total : zone.start) |
| 328 | + : zone.isLast ? delta.total * this.size : zone.start * this.size) |
322 | 329 | ) |
323 | 330 | } |
324 | 331 |
|
|
0 commit comments