|
56 | 56 | var bench = this.bench || this.remain
|
57 | 57 | var keeps = this.remain + bench
|
58 | 58 | var slots = this.$slots.default
|
59 |
| - var total = slots && slots.length || 0 |
| 59 | + var total = (slots && slots.length) || 0 |
60 | 60 |
|
61 | 61 | this.delta = {
|
62 |
| - start: start, // start index. |
63 |
| - end: start + keeps, // end index. |
64 |
| - total: total, // all items count. |
65 |
| - keeps: keeps, // nums keeping in real dom. |
66 |
| - bench: bench, // nums scroll pass should force update. |
67 |
| - offset: 0, // cache scrollTop offset. |
68 |
| - direct: 'd', // cache scroll direction. |
69 |
| - height: height, // container wrapper viewport height. |
70 |
| - fireTime: 0, // cache last event fire time avoid compact. |
71 |
| - paddingTop: 0, // container wrapper real padding-top. |
72 |
| - paddingBottom: 0, // container wrapper real padding-bottom. |
73 |
| - variableData: {} // cache variable index height and padding offset. |
| 62 | + start: start, // start index. |
| 63 | + end: start + keeps, // end index. |
| 64 | + total: total, // all items count. |
| 65 | + keeps: keeps, // nums keeping in real dom. |
| 66 | + bench: bench, // nums scroll pass should force update. |
| 67 | + offset: 0, // cache scrollTop offset. |
| 68 | + direct: 'd', // cache scroll direction. |
| 69 | + height: height, // container wrapper viewport height. |
| 70 | + fireTime: 0, // cache last event fire time avoid compact. |
| 71 | + paddingTop: 0, // container wrapper real padding-top. |
| 72 | + paddingBottom: 0, // container wrapper real padding-bottom. |
| 73 | + varCache: {}, // cache variable index height and padding offset. |
| 74 | + averageSize: 0, // average/estimate item height before variable be calculated. |
| 75 | + lastCalcIndex: 0 // last calculated variable height/offset index, always increase. |
74 | 76 | }
|
75 | 77 | },
|
76 | 78 |
|
|
154 | 156 |
|
155 | 157 | delta.end = end
|
156 | 158 | delta.start = start
|
157 |
| - |
158 |
| - // call component to update shown items. |
159 | 159 | this.$forceUpdate()
|
160 | 160 | },
|
161 | 161 |
|
162 | 162 | // return the scroll passed items count in variable height.
|
163 | 163 | getVarOvers: function (offset) {
|
| 164 | + var delta = this.delta |
164 | 165 | var low = 0
|
165 |
| - var high = this.delta.total |
166 |
| - |
167 | 166 | var middle = 0
|
168 | 167 | var middleOffset = 0
|
| 168 | + var high = delta.total |
| 169 | + |
169 | 170 | while (low <= high) {
|
170 | 171 | middle = low + Math.floor((high - low) / 2)
|
171 | 172 | middleOffset = this.getVarOffset(middle)
|
172 | 173 |
|
| 174 | + // calculate the averageSize at first binary search. |
| 175 | + if (!delta.averageSize) { |
| 176 | + delta.averageSize = Math.floor(middleOffset / middle) |
| 177 | + } |
| 178 | + |
173 | 179 | if (middleOffset === offset) {
|
174 | 180 | return middle
|
175 | 181 | } else if (middleOffset < offset) {
|
|
184 | 190 |
|
185 | 191 | // get the variable height index scroll offset.
|
186 | 192 | getVarOffset: function (index) {
|
187 |
| - var i = index |
| 193 | + var delta = this.delta |
| 194 | + var cache = delta.varCache[index] |
| 195 | + |
| 196 | + if (cache) { |
| 197 | + return cache.offset |
| 198 | + } |
| 199 | + |
188 | 200 | var offset = 0
|
189 |
| - while (i--) { |
190 |
| - offset += this.getVarSize(i) |
| 201 | + for (var i = 0; i < index; i++) { |
| 202 | + var size = this.getVarSize(i) |
| 203 | + delta.varCache[i] = { |
| 204 | + size: size, |
| 205 | + offset: offset |
| 206 | + } |
| 207 | + offset += size |
191 | 208 | }
|
192 | 209 |
|
| 210 | + delta.lastCalcIndex = Math.max(delta.lastCalcIndex, index) |
| 211 | + |
193 | 212 | return offset
|
194 | 213 | },
|
195 | 214 |
|
196 | 215 | // return a variable size (height) from a given index.
|
197 | 216 | getVarSize: function (index) {
|
198 |
| - return this.variable(index) || 0 |
| 217 | + var cache = this.delta.varCache[index] |
| 218 | + return (cache && cache.size) || this.variable(index) || 0 |
| 219 | + }, |
| 220 | + |
| 221 | + // return the paddingBottom when variable height base current zone. |
| 222 | + getVarPaddingBottom () { |
| 223 | + var delta = this.delta |
| 224 | + var rest = delta.total - delta.lastCalcIndex |
| 225 | + if (rest <= delta.keeps || delta.lastCalcIndex >= delta.total) { |
| 226 | + return this.getVarOffset(delta.total) - this.getVarOffset(delta.end) |
| 227 | + } else { |
| 228 | + // if unreached last zone or uncalculate real behind offset |
| 229 | + // continue return the estimate paddingBottom avoid max calculate. |
| 230 | + return (delta.total - delta.lastCalcIndex) * (delta.averageSize || this.size) |
| 231 | + } |
199 | 232 | },
|
200 | 233 |
|
201 | 234 | // avoid overflow range.
|
|
253 | 286 |
|
254 | 287 | if (this.variable) {
|
255 | 288 | paddingTop = hasPadding ? this.getVarOffset(delta.start) : 0
|
256 |
| - paddingBottom = hasPadding ? this.getVarOffset(delta.total) - this.getVarOffset(delta.end) : 0 |
| 289 | + paddingBottom = hasPadding ? this.getVarPaddingBottom() : 0 |
257 | 290 | } else {
|
258 | 291 | paddingTop = this.size * (hasPadding ? delta.start : 0)
|
259 | 292 | paddingBottom = this.size * (hasPadding ? slots.length - delta.keeps : 0) - paddingTop
|
|
0 commit comments