tencent.jquery.pix.component 1.0.91-beta1 → 1.0.91-beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/change.md +4 -0
- package/components/list/list.js +25 -64
- package/package.json +1 -1
package/change.md
CHANGED
package/components/list/list.js
CHANGED
|
@@ -55,13 +55,25 @@ List.prototype.init = function () {
|
|
|
55
55
|
</div>
|
|
56
56
|
`);
|
|
57
57
|
|
|
58
|
-
//
|
|
58
|
+
// 【优化】缓存 DOM 引用,避免每次滚动都执行 jQuery 查询
|
|
59
|
+
this.$container = $container;
|
|
60
|
+
this.$scrollWrapper = $container.find('.virtual-list-scroll');
|
|
61
|
+
this.$viewport = $container.find('.virtual-list-viewport');
|
|
62
|
+
// 【优化】缓存容器高度,固定高度容器无需每次重新计算(避免触发 reflow)
|
|
63
|
+
this._viewportHeight = $container.height();
|
|
64
|
+
|
|
65
|
+
// 【优化】绑定滚动事件(真正的 rAF 节流:一帧内只执行一次 updateVisibleItems)
|
|
66
|
+
this._rafPending = false;
|
|
59
67
|
$container.off().on('scroll', function () {
|
|
60
68
|
self.scrollTop = $(this).scrollTop();
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
self.
|
|
64
|
-
|
|
70
|
+
if (!self._rafPending) {
|
|
71
|
+
self._rafPending = true;
|
|
72
|
+
window.requestAnimationFrame(() => {
|
|
73
|
+
self._rafPending = false;
|
|
74
|
+
self.updateVisibleItems();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
65
77
|
|
|
66
78
|
if (options.onscroll && options.onscroll.constructor === Function) {
|
|
67
79
|
options.onscroll(this, self.scrollTop);
|
|
@@ -78,12 +90,12 @@ List.prototype.init = function () {
|
|
|
78
90
|
List.prototype.updateVisibleItems = function (force = false) {
|
|
79
91
|
const self = this;
|
|
80
92
|
const options = this.options;
|
|
81
|
-
const $container = $(options.container);
|
|
82
93
|
|
|
83
94
|
let startIndex = 0; // 起始索引
|
|
84
95
|
let endIndex = 0; // 结束索引
|
|
85
96
|
|
|
86
|
-
|
|
97
|
+
// 【优化】使用缓存的容器高度,避免每次滚动触发布局计算
|
|
98
|
+
const viewportHeight = this._viewportHeight;
|
|
87
99
|
// 计算当前可见项范围(含缓冲区)
|
|
88
100
|
startIndex = Math.max(0, Math.floor(self.scrollTop / options.itemHeight) - options.buffer);
|
|
89
101
|
endIndex = Math.min(
|
|
@@ -91,8 +103,8 @@ List.prototype.updateVisibleItems = function (force = false) {
|
|
|
91
103
|
Math.ceil((self.scrollTop + viewportHeight) / options.itemHeight) + options.buffer
|
|
92
104
|
);
|
|
93
105
|
|
|
94
|
-
//
|
|
95
|
-
const $viewport =
|
|
106
|
+
// 【优化】使用缓存的 $viewport 引用
|
|
107
|
+
const $viewport = this.$viewport;
|
|
96
108
|
|
|
97
109
|
/**方案1 */
|
|
98
110
|
const newActiveNodes = new Map();
|
|
@@ -128,7 +140,8 @@ List.prototype.updateVisibleItems = function (force = false) {
|
|
|
128
140
|
);
|
|
129
141
|
$viewport.append($node);
|
|
130
142
|
} else {
|
|
131
|
-
|
|
143
|
+
// 【优化】nodePool 中已经是 jQuery 对象,无需再次 $() 包装
|
|
144
|
+
$node = this.nodePool.pop();
|
|
132
145
|
$node.css('transform', `translateY(${top}px)`).attr('data-index', i);
|
|
133
146
|
self.updateRenderUI($node, options.data[i], i);
|
|
134
147
|
}
|
|
@@ -142,67 +155,15 @@ List.prototype.updateVisibleItems = function (force = false) {
|
|
|
142
155
|
this.nodePool.push($node);
|
|
143
156
|
});
|
|
144
157
|
this.activeNodes = newActiveNodes;
|
|
145
|
-
|
|
146
|
-
/**方案2 */
|
|
147
|
-
// const $existingChildren = $viewport.children(); // 获取现有 DOM 元素集合
|
|
148
|
-
// const usedIndices = new Set(); // 记录当前需要保留的索引
|
|
149
|
-
|
|
150
|
-
// // 步骤 1:更新或保留现有元素
|
|
151
|
-
// if ($existingChildren.length > 0) {
|
|
152
|
-
// for (let j = 0; j < $existingChildren.length; j++) {
|
|
153
|
-
// const $el = $($existingChildren[j]);
|
|
154
|
-
// const oldIndex = parseInt($el.data('data-index'));
|
|
155
|
-
// if (oldIndex >= startIndex && oldIndex <= endIndex) {
|
|
156
|
-
// // 仍在可视范围内 → 更新位置和内容
|
|
157
|
-
// const newTop = oldIndex * options.itemHeight;
|
|
158
|
-
// $el.css('top', `${newTop}px`);
|
|
159
|
-
// usedIndices.add(oldIndex);
|
|
160
|
-
// } else {
|
|
161
|
-
// // 移出可视范围 → 从 DOM 中删除
|
|
162
|
-
// $el.remove();
|
|
163
|
-
// }
|
|
164
|
-
// }
|
|
165
|
-
// }
|
|
166
|
-
|
|
167
|
-
// // 步骤 2:补充新增元素
|
|
168
|
-
// for (let i = startIndex; i <= endIndex; i++) {
|
|
169
|
-
// if (!usedIndices.has(i)) {
|
|
170
|
-
// // 需要新增的元素
|
|
171
|
-
// const top = i * options.itemHeight;
|
|
172
|
-
// const $element = $(
|
|
173
|
-
// `<div class="virtual-item"
|
|
174
|
-
// style="position: absolute; top: ${top}px; height: ${options.itemHeight}px"
|
|
175
|
-
// data-index="${i}">
|
|
176
|
-
// ${options.renderItem(options.data[i], i)}
|
|
177
|
-
// </div>`
|
|
178
|
-
// );
|
|
179
|
-
// // 插入到正确位置(按索引顺序)
|
|
180
|
-
// let inserted = false;
|
|
181
|
-
// for (let j = 0; j < $existingChildren.length; j++) {
|
|
182
|
-
// const $el = $($existingChildren[j]);
|
|
183
|
-
// const currentIndex = parseInt($el.data('data-index'));
|
|
184
|
-
// if (currentIndex > i) {
|
|
185
|
-
// $element.insertBefore($el);
|
|
186
|
-
// inserted = true;
|
|
187
|
-
// break;
|
|
188
|
-
// }
|
|
189
|
-
// }
|
|
190
|
-
|
|
191
|
-
// if (!inserted) {
|
|
192
|
-
// $viewport.append($element);
|
|
193
|
-
// }
|
|
194
|
-
// }
|
|
195
|
-
// }
|
|
196
|
-
|
|
197
158
|
}
|
|
198
159
|
|
|
199
160
|
// 外部更新数据方法
|
|
200
161
|
List.prototype.updateData = function (newData) {
|
|
201
162
|
const options = this.options;
|
|
202
163
|
options.data = newData;
|
|
203
|
-
const totalHeight = options.data.length * options.itemHeight
|
|
204
|
-
//
|
|
205
|
-
|
|
164
|
+
const totalHeight = options.data.length * options.itemHeight;
|
|
165
|
+
// 【优化】使用缓存的 DOM 引用,避免重新创建 jQuery 对象
|
|
166
|
+
this.$scrollWrapper.height(`${totalHeight}px`);
|
|
206
167
|
this.updateVisibleItems(true); // 强制更新渲染
|
|
207
168
|
};
|
|
208
169
|
|