|
27 | 27 | onscroll: Function
|
28 | 28 | },
|
29 | 29 |
|
30 |
| - // An object helping to calculate. |
31 |
| - delta: { |
32 |
| - start: 0, // Start index. |
33 |
| - end: 0, // End index. |
34 |
| - total: 0, // All items count. |
35 |
| - keeps: 0, // Nums of item keeping in real dom. |
36 |
| - viewHeight: 0, // Container wrapper viewport height. |
37 |
| - allPadding: 0, // All padding of not-render-yet doms. |
38 |
| - paddingTop: 0, // Container wrapper real padding-top. |
39 |
| - scrollTop: 0, // Store scrollTop. |
40 |
| - scrollDirect: 'd', // Scroll direction. |
41 |
| - fireTime: 0 // Store last event time avoiding compact fire. |
| 30 | + created: function () { |
| 31 | + // An object helping to calculate. |
| 32 | + this.delta = { |
| 33 | + start: 0, // Start index. |
| 34 | + end: 0, // End index. |
| 35 | + total: 0, // All items count. |
| 36 | + keeps: 0, // Nums keeping in real dom. |
| 37 | + benchs: 0, // Nums scroll pass should force update. |
| 38 | + scrollTop: 0, // Store scrollTop. |
| 39 | + scrollDirect: 'd', // Scroll direction. |
| 40 | + viewHeight: 0, // Container wrapper viewport height. |
| 41 | + allPadding: 0, // All padding of not-render-yet doms. |
| 42 | + paddingTop: 0, // Container wrapper real padding-top. |
| 43 | + timeStamp: 0 // Last event fire timestamp avoid compact fire. |
| 44 | + } |
42 | 45 | },
|
43 | 46 |
|
44 | 47 | watch: {
|
45 | 48 | start: function (index) {
|
46 |
| - var delta = this.$options.delta |
| 49 | + var delta = this.delta |
47 | 50 |
|
48 |
| - if (index !== parseInt(index, 10)) { |
49 |
| - return console.warn(innerns + ': start ' + index + ' is not integer.') |
50 |
| - } |
51 |
| - if (index < 0 || index > delta.total - 1) { |
52 |
| - return console.warn(innerns + ': start ' + index + ' is overflow.') |
| 51 | + if (!this.validStart(index)) { |
| 52 | + return |
53 | 53 | }
|
54 | 54 |
|
55 | 55 | var start, end, scrollTop
|
|
85 | 85 | },
|
86 | 86 |
|
87 | 87 | updateZone: function (offset) {
|
88 |
| - var delta = this.$options.delta |
| 88 | + var delta = this.delta |
89 | 89 | var overs = Math.floor(offset / this.size)
|
90 | 90 |
|
91 | 91 | if (!offset && delta.total) {
|
|
95 | 95 | delta.scrollDirect = delta.scrollTop > offset ? 'u' : 'd'
|
96 | 96 | delta.scrollTop = offset
|
97 | 97 |
|
98 |
| - // Need moving items at lease one unit height. |
99 |
| - // @todo: consider prolong the zone range size. |
| 98 | + // Calculate the start and end by moving items. |
100 | 99 | var start = overs || 0
|
101 | 100 | var end = overs ? (overs + delta.keeps) : delta.keeps
|
102 | 101 |
|
|
106 | 105 | start = zone.start
|
107 | 106 | }
|
108 | 107 |
|
| 108 | + // If scroll pass items within now benchs, do not update. |
| 109 | + if (overs > delta.start && overs - delta.start <= delta.benchs) { |
| 110 | + return |
| 111 | + } |
| 112 | + |
109 | 113 | delta.end = end
|
110 | 114 | delta.start = start
|
111 | 115 |
|
|
115 | 119 |
|
116 | 120 | // Avoid overflow range.
|
117 | 121 | isOverflow: function (start) {
|
118 |
| - var delta = this.$options.delta |
| 122 | + var delta = this.delta |
119 | 123 | var overflow = delta.total - delta.keeps > 0 && (start + this.remain >= delta.total)
|
120 | 124 | if (overflow && delta.scrollDirect === 'd') {
|
121 | 125 | this.fireEvent('tobottom')
|
|
125 | 129 |
|
126 | 130 | // Fire a props event to parent.
|
127 | 131 | fireEvent: function (event) {
|
128 |
| - var cb = this[event] |
129 | 132 | var now = +new Date()
|
130 |
| - var delta = this.$options.delta |
131 |
| - if (cb && (now - delta.fireTime > 35)) { |
132 |
| - cb() |
133 |
| - delta.fireTime = now |
| 133 | + if (this[event] && now - this.delta.timeStamp > 30) { |
| 134 | + this[event]() |
| 135 | + this.delta.timeStamp = now |
134 | 136 | }
|
135 | 137 | },
|
136 | 138 |
|
| 139 | + // Check if given start is valid. |
| 140 | + validStart: function (start) { |
| 141 | + let valid = 1 |
| 142 | + if (start !== parseInt(start, 10)) { |
| 143 | + valid = 0 |
| 144 | + console.warn(innerns + ': start ' + start + ' is not an integer.') |
| 145 | + } |
| 146 | + if (start < 0 || start > this.delta.total - 1) { |
| 147 | + valid = 0 |
| 148 | + console.warn(innerns + ': start ' + start + ' is an overflow index.') |
| 149 | + } |
| 150 | + return !!valid |
| 151 | + }, |
| 152 | + |
137 | 153 | // If overflow range return the last zone.
|
138 | 154 | getLastZone: function () {
|
139 |
| - var delta = this.$options.delta |
140 | 155 | return {
|
141 |
| - end: delta.total, |
142 |
| - start: delta.total - delta.keeps |
| 156 | + end: this.delta.total, |
| 157 | + start: this.delta.total - this.delta.keeps |
143 | 158 | }
|
144 | 159 | },
|
145 | 160 |
|
|
148 | 163 | this.$refs.container.scrollTop = scrollTop
|
149 | 164 | },
|
150 | 165 |
|
| 166 | + // Filter the shown items base on start and end. |
151 | 167 | filter: function (slots) {
|
152 |
| - var delta = this.$options.delta |
| 168 | + var delta = this.delta |
153 | 169 |
|
154 | 170 | if (!slots) {
|
155 | 171 | slots = []
|
|
167 | 183 | },
|
168 | 184 |
|
169 | 185 | beforeMount: function () {
|
170 |
| - var remains = this.remain |
171 |
| - var delta = this.$options.delta |
172 |
| - var benchs = Math.round(remains / 2) |
173 |
| - |
174 |
| - delta.start = this.start >= remains ? this.start : 0 |
175 |
| - delta.end = this.start + remains + benchs |
176 |
| - delta.keeps = remains + benchs |
177 |
| - delta.viewHeight = this.size * remains |
| 186 | + var delta = this.delta |
| 187 | + var remain = this.remain |
| 188 | + var benchs = Math.round(remain / 2) |
| 189 | + |
| 190 | + delta.benchs = benchs |
| 191 | + delta.keeps = remain + benchs |
| 192 | + delta.viewHeight = this.size * remain |
| 193 | + delta.start = this.start >= remain ? this.start : 0 |
| 194 | + delta.end = this.start + remain + benchs |
178 | 195 | },
|
179 | 196 |
|
180 | 197 | mounted: function () {
|
181 |
| - this.setScrollTop(this.start * this.size) |
| 198 | + if (this.validStart(this.start)) { |
| 199 | + this.setScrollTop(this.start * this.size) |
| 200 | + } |
182 | 201 | },
|
183 | 202 |
|
184 | 203 | render: function (createElement) {
|
185 | 204 | var showList = this.filter(this.$slots.default)
|
186 |
| - var delta = this.$options.delta |
| 205 | + var delta = this.delta |
187 | 206 |
|
188 | 207 | return createElement(this.rtag, {
|
189 | 208 | 'ref': 'container',
|
|
0 commit comments