|
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