|
1 |
| -<div ref:viewport on:scroll='handleScroll()' style='height: {height};'> |
| 1 | +<div ref:viewport on:scroll='refresh()' style='height: {height};'> |
2 | 2 | <div ref:container style='padding-top: {top}px; padding-bottom: {bottom}px;'>
|
3 | 3 | {#each visible as item (item.index)}
|
4 | 4 | <div class='row'>
|
|
38 | 38 | const { viewport, container } = this.refs;
|
39 | 39 | const viewportHeight = viewport.offsetHeight;
|
40 | 40 |
|
41 |
| - const keys = Object.keys(this.options.data).filter(key => key !== 'items' && key !== 'component' && key !== 'itemHeight'); |
| 41 | + const keys = Object.keys(this.options.data).filter(key => key !== 'items' && key !== 'component' && key !== 'height' && key !== 'itemHeight'); |
42 | 42 | if (keys.length) {
|
43 | 43 | const state = this.get();
|
44 | 44 | keys.forEach(key => {
|
45 | 45 | _props[key] = state[key];
|
46 | 46 | });
|
47 | 47 | this.set({ _props });
|
48 |
| - |
49 |
| - this.on('state', ({ changed, current }) => { |
50 |
| - if (!keys.some(key => changed[key])) return; |
51 |
| - |
52 |
| - const _props = {}; |
53 |
| - keys.forEach(key => { |
54 |
| - _props[key] = current[key]; |
55 |
| - }); |
56 |
| - this.set({ _props }); |
57 |
| - }); |
58 | 48 | }
|
59 | 49 |
|
60 | 50 | this.rows = container.getElementsByClassName('row');
|
|
89 | 79 | bottom: (items.length - end) * avg
|
90 | 80 | });
|
91 | 81 | }
|
| 82 | + |
| 83 | + this.on('state', ({ changed, previous, current }) => { |
| 84 | + if (changed.items || changed.height || changed.itemHeight) { |
| 85 | + if (current.itemHeight && (changed.itemHeight || current.items.length !== this.heightMap.length)) { |
| 86 | + this.heightMap = current.items.map(() => current.itemHeight); |
| 87 | + } |
| 88 | + |
| 89 | + this.refresh(); |
| 90 | + } |
| 91 | + |
| 92 | + if (keys.some(key => changed[key])) { |
| 93 | + const _props = {}; |
| 94 | + keys.forEach(key => { |
| 95 | + _props[key] = current[key]; |
| 96 | + }); |
| 97 | + this.set({ _props }); |
| 98 | + } |
| 99 | + }); |
92 | 100 | },
|
93 | 101 |
|
94 | 102 | methods: {
|
95 |
| - handleScroll() { |
| 103 | + refresh() { |
96 | 104 | const { items, start, end, itemHeight } = this.get();
|
97 | 105 | const { offsetHeight, scrollTop } = this.refs.viewport;
|
98 | 106 |
|
99 | 107 | let paddingTop = 0;
|
100 | 108 | let offset = 0;
|
101 | 109 | let i = 0;
|
102 | 110 |
|
103 |
| - if (itemHeight) { |
104 |
| - if (this.heightMap.length !== items.length) { |
105 |
| - this.heightMap = items.map(item => itemHeight); |
106 |
| - } |
107 |
| - } else { |
| 111 | + if (!itemHeight) { |
108 | 112 | for (let v = 0; v < this.rows.length; v += 1) {
|
109 | 113 | this.heightMap[start + v] = this.rows[v].offsetHeight;
|
110 | 114 | }
|
111 | 115 | }
|
112 | 116 |
|
113 | 117 | for (; i < items.length; i += 1) {
|
| 118 | + if (!(i in this.heightMap)) break; |
| 119 | + |
114 | 120 | offset += this.heightMap[i];
|
115 | 121 | if (offset > scrollTop) break;
|
116 | 122 |
|
|
120 | 126 | const newStart = i++;
|
121 | 127 |
|
122 | 128 | for (; i < items.length; i += 1) {
|
123 |
| - if (offset > scrollTop + offsetHeight) break; |
| 129 | + if (offset >= scrollTop + offsetHeight) break; |
124 | 130 | offset += this.heightMap[i];
|
125 | 131 | }
|
126 | 132 |
|
|
0 commit comments