tencent.jquery.pix.component 1.0.65 → 1.0.66-beta1
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/components/waterfall/waterfall.js +144 -123
- package/package.json +1 -1
|
@@ -17,6 +17,7 @@ const DEFAULTS = {
|
|
|
17
17
|
renderItem(data, index) { // 元素首次渲染时的回调函数, 如果把updateItem设置为空,那么更新时则会兜底触发renderItem
|
|
18
18
|
return '<div class="waterfall-item"></div>';
|
|
19
19
|
},
|
|
20
|
+
scrollDom: null, // 滚动元素,如果传入了滚动元素,那么用来计算的窗口高度就以滚动元素的高度为准
|
|
20
21
|
// 传入 $node, data, index
|
|
21
22
|
updateItem: null, // 元素更新时的回调函数
|
|
22
23
|
onscroll: null, // 滚动事件回调函数
|
|
@@ -127,6 +128,7 @@ Waterfall.prototype.init = function () {
|
|
|
127
128
|
const self = this;
|
|
128
129
|
const options = this.options;
|
|
129
130
|
const $container = $(options.container);
|
|
131
|
+
const $scrollDom = options.scrollDom ? $(options.scrollDom) : $container;
|
|
130
132
|
|
|
131
133
|
this.nodePool = []; // DOM 节点池
|
|
132
134
|
this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
|
|
@@ -153,7 +155,7 @@ Waterfall.prototype.init = function () {
|
|
|
153
155
|
}
|
|
154
156
|
|
|
155
157
|
// 绑定滚动事件(节流处理)
|
|
156
|
-
$
|
|
158
|
+
$scrollDom.off().on('scroll', function () {
|
|
157
159
|
self.scrollTop = $(this).scrollTop();
|
|
158
160
|
|
|
159
161
|
window.requestAnimationFrame(() => {
|
|
@@ -165,7 +167,7 @@ Waterfall.prototype.init = function () {
|
|
|
165
167
|
}
|
|
166
168
|
});
|
|
167
169
|
|
|
168
|
-
this.scrollTop = $
|
|
170
|
+
this.scrollTop = $scrollDom.scrollTop(); // 当前滚动位置
|
|
169
171
|
|
|
170
172
|
// 首次渲染
|
|
171
173
|
self.updateVisibleItems();
|
|
@@ -176,11 +178,17 @@ Waterfall.prototype.init = function () {
|
|
|
176
178
|
Waterfall.prototype.updateVisibleItems = function (force = false) {
|
|
177
179
|
const self = this;
|
|
178
180
|
const options = this.options;
|
|
179
|
-
|
|
181
|
+
let h = 0;
|
|
182
|
+
if (options.scrollDom) {
|
|
183
|
+
h = $(options.scrollDom).height();
|
|
184
|
+
} else {
|
|
185
|
+
h = $(options.container).height();
|
|
186
|
+
}
|
|
180
187
|
|
|
181
188
|
const startTop = self.scrollTop; // 当前滚动位置
|
|
182
|
-
const endTop = startTop +
|
|
189
|
+
const endTop = startTop + h;
|
|
183
190
|
// console.log('startTop', startTop)
|
|
191
|
+
console.log('endTop', endTop)
|
|
184
192
|
|
|
185
193
|
// 进行可见区域的渲染更新
|
|
186
194
|
this.updateCardsInView({
|
|
@@ -231,13 +239,13 @@ Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
|
|
|
231
239
|
}
|
|
232
240
|
|
|
233
241
|
// 获取指定高度下的卡片索引
|
|
234
|
-
Waterfall.prototype.updateCardsInView = function ({ start, end, force = false }) {
|
|
242
|
+
Waterfall.prototype.updateCardsInView = async function ({ start, end, force = false }) {
|
|
235
243
|
const options = this.options;
|
|
236
244
|
const minHeight = this.getMinHeight();
|
|
237
245
|
const endBuffer = end + options.bufferHeight;
|
|
238
246
|
if (minHeight < endBuffer) {
|
|
239
247
|
// 如果不够 进行补建
|
|
240
|
-
this.createCards({ end: endBuffer });
|
|
248
|
+
await this.createCards({ end: endBuffer });
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
const startNum = start - options.bufferHeight;
|
|
@@ -403,124 +411,125 @@ Waterfall.prototype.getMinHeightColumn = function () {
|
|
|
403
411
|
}
|
|
404
412
|
|
|
405
413
|
// 创建卡片
|
|
406
|
-
Waterfall.prototype.createCards = function ({ end, dataId = -1 }) {
|
|
414
|
+
Waterfall.prototype.createCards = function ({ end, dataId = -1 }, callback) {
|
|
407
415
|
const self = this;
|
|
408
416
|
const options = this.options;
|
|
409
|
-
const $container = $(options.container);
|
|
410
417
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
418
|
+
return new Promise((resolve) => {
|
|
419
|
+
// 新方案:获取下一个未渲染的数据ID
|
|
420
|
+
let nextDataId = null;
|
|
421
|
+
for (let [dataId, dataInfo] of this.dataIdMap) {
|
|
422
|
+
if (!this.renderedDataIds.has(dataId)) {
|
|
423
|
+
nextDataId = dataId;
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
417
426
|
}
|
|
418
|
-
}
|
|
419
427
|
|
|
420
428
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const dataInfo = this.dataIdMap.get(nextDataId);
|
|
430
|
-
if (!dataInfo || !dataInfo.data) {
|
|
431
|
-
console.warn('Waterfall: Invalid data for dataId', nextDataId);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
429
|
+
// 如果没有更多数据需要渲染
|
|
430
|
+
if (nextDataId === null) {
|
|
431
|
+
this.setScrollHeight();
|
|
432
|
+
return resolve();
|
|
433
|
+
}
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
435
|
+
const dataInfo = this.dataIdMap.get(nextDataId);
|
|
436
|
+
if (!dataInfo || !dataInfo.data) {
|
|
437
|
+
console.warn('Waterfall: Invalid data for dataId', nextDataId);
|
|
438
|
+
return resolve();
|
|
439
|
+
}
|
|
439
440
|
|
|
440
|
-
|
|
441
|
+
if (this.renderIndex >= options.data.length) {
|
|
442
|
+
this.setScrollHeight();
|
|
443
|
+
return resolve();
|
|
444
|
+
}
|
|
441
445
|
|
|
442
|
-
|
|
443
|
-
if (column === null) {
|
|
444
|
-
column = this.columnItems[0];
|
|
445
|
-
}
|
|
446
|
+
const data = options.data[nextDataId];
|
|
446
447
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
448
|
+
let column = this.getMinHeightColumn();
|
|
449
|
+
if (column === null) {
|
|
450
|
+
column = this.columnItems[0];
|
|
451
|
+
}
|
|
450
452
|
|
|
451
|
-
|
|
453
|
+
const top = column.bottom === 0 ? options.marginTop : (column.bottom + options.rowGap);
|
|
454
|
+
const position = { top, left: column.left };
|
|
455
|
+
const row = createDefaultRow(position);
|
|
452
456
|
|
|
453
|
-
|
|
457
|
+
this.renderIndex += 1;
|
|
454
458
|
|
|
455
|
-
|
|
456
|
-
if (options.shouldOccupySpace) {
|
|
457
|
-
specialNode = options.shouldOccupySpace(data) || false;
|
|
458
|
-
}
|
|
459
|
+
let specialNode = false;
|
|
459
460
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
$card = this.appendCard(data, nextDataId, position);
|
|
464
|
-
} else {
|
|
465
|
-
const $tmp = getNodePoolPop(this.nodePool, this.activeNodes);
|
|
466
|
-
if ($tmp) {
|
|
467
|
-
$card = $tmp;
|
|
468
|
-
$card.css({
|
|
469
|
-
'transform': `translate(${row.left}px,${row.top}px)`,
|
|
470
|
-
}).attr('data-index', nextDataId);
|
|
471
|
-
this.updateRenderUI($card, data, nextDataId);
|
|
472
|
-
} else {
|
|
473
|
-
$card = this.appendCard(data, nextDataId, position);
|
|
461
|
+
// 如果是特殊的卡片,需要指定节点不变更的数据,那么该数据的节点不能被其他数据使用
|
|
462
|
+
if (options.shouldOccupySpace) {
|
|
463
|
+
specialNode = options.shouldOccupySpace(data) || false;
|
|
474
464
|
}
|
|
475
465
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
466
|
+
// 添加卡片,使用dataId作为唯一标识
|
|
467
|
+
let $card = null;
|
|
468
|
+
if (this.nodePool.length === 0 || specialNode === true) {
|
|
469
|
+
$card = this.appendCard(data, nextDataId, position);
|
|
470
|
+
} else {
|
|
471
|
+
const $tmp = getNodePoolPop(this.nodePool, this.activeNodes);
|
|
472
|
+
if ($tmp) {
|
|
473
|
+
$card = $tmp;
|
|
474
|
+
$card.css({
|
|
475
|
+
'transform': `translate(${row.left}px,${row.top}px)`,
|
|
476
|
+
}).attr('data-index', nextDataId);
|
|
477
|
+
this.updateRenderUI($card, data, nextDataId);
|
|
478
|
+
} else {
|
|
479
|
+
$card = this.appendCard(data, nextDataId, position);
|
|
480
|
+
}
|
|
483
481
|
|
|
484
|
-
|
|
485
|
-
// dataInfo.layoutInfo = {
|
|
486
|
-
// //columnIndex: this.columnItems.indexOf(column),
|
|
487
|
-
// //position: position,
|
|
488
|
-
// // row: row
|
|
489
|
-
// };
|
|
482
|
+
}
|
|
490
483
|
|
|
484
|
+
row.$node = $card;
|
|
485
|
+
row.dataId = nextDataId; // 使用dataId替代renderIndex
|
|
486
|
+
if (dataId !== -1) {
|
|
487
|
+
row.dataId = dataId;
|
|
488
|
+
}
|
|
491
489
|
|
|
490
|
+
if (specialNode === false) {
|
|
491
|
+
// 把新增的卡片放进 activeNodes 当成活跃节点元素,那么是 可以动态使用的
|
|
492
|
+
this.activeNodes.set(nextDataId, $card);
|
|
492
493
|
|
|
494
|
+
this.allReadyNodes.set(nextDataId, $card);
|
|
495
|
+
} else {
|
|
496
|
+
// 如果是特殊的,这里不要记录了
|
|
497
|
+
this.allReadyNodes.set(nextDataId, null);
|
|
498
|
+
}
|
|
493
499
|
|
|
494
|
-
|
|
495
|
-
// 把新增的卡片放进 activeNodes 当成活跃节点元素,那么是 可以动态使用的
|
|
496
|
-
this.activeNodes.set(nextDataId, $card);
|
|
500
|
+
this.renderedDataIds.add(nextDataId);
|
|
497
501
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
502
|
+
setTimeout(() => {
|
|
503
|
+
window.requestAnimationFrame(() => {
|
|
504
|
+
// 更新列的底部距离
|
|
505
|
+
column.bottom = top + $card.height();
|
|
506
|
+
console.log('column.bottom', column.bottom, $card.height());
|
|
507
|
+
column.children.push(row);
|
|
508
|
+
row.bottom = column.bottom;
|
|
503
509
|
|
|
504
|
-
|
|
510
|
+
// 检查是否需要继续创建卡片
|
|
511
|
+
const minHeight = this.getMinHeight();
|
|
512
|
+
const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
|
|
505
513
|
|
|
506
|
-
|
|
507
|
-
column.bottom = top + $card.height();
|
|
508
|
-
column.children.push(row);
|
|
509
|
-
row.bottom = column.bottom;
|
|
514
|
+
if (hasMoreData && (minHeight < end)) {
|
|
510
515
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
516
|
+
this.createCards({ end }, () => {
|
|
517
|
+
resolve();
|
|
518
|
+
if (callback) {
|
|
519
|
+
callback();
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
} else {
|
|
523
|
+
this.setScrollHeight();
|
|
524
|
+
resolve();
|
|
525
|
+
if (callback) {
|
|
526
|
+
callback();
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
}, 42);
|
|
531
|
+
});
|
|
514
532
|
|
|
515
|
-
if (hasMoreData && (minHeight < end)) {
|
|
516
|
-
window.requestAnimationFrame(() => {
|
|
517
|
-
this.createCards({ end });
|
|
518
|
-
});
|
|
519
|
-
} else {
|
|
520
|
-
// const maxHeight = this.getMaxHeight();
|
|
521
|
-
// $(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
|
|
522
|
-
this.setScrollHeight();
|
|
523
|
-
}
|
|
524
533
|
}
|
|
525
534
|
|
|
526
535
|
|
|
@@ -563,7 +572,7 @@ Waterfall.prototype.updateRenderUI = function ($node, data, dataId) {
|
|
|
563
572
|
|
|
564
573
|
|
|
565
574
|
|
|
566
|
-
Waterfall.prototype.updateData = function (newData) {
|
|
575
|
+
Waterfall.prototype.updateData = async function (newData) {
|
|
567
576
|
const options = this.options;
|
|
568
577
|
options.data = newData;
|
|
569
578
|
|
|
@@ -573,23 +582,45 @@ Waterfall.prototype.updateData = function (newData) {
|
|
|
573
582
|
//this.nextDataId = 0;
|
|
574
583
|
|
|
575
584
|
// 为每个数据项分配唯一ID
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
this.createCards({ end: 0, dataId });
|
|
585
|
+
let bool = true
|
|
586
|
+
let count = options.data.length - 1;
|
|
587
|
+
let index = 0;
|
|
588
|
+
|
|
589
|
+
while (bool) {
|
|
590
|
+
if (index > count) {
|
|
591
|
+
bool = false
|
|
592
|
+
this.updateVisibleItems(true); // 强制更新渲染
|
|
593
|
+
break;
|
|
586
594
|
}
|
|
587
|
-
});
|
|
588
595
|
|
|
589
|
-
|
|
596
|
+
const dataId = index;
|
|
597
|
+
this.dataIdMap.set(dataId, {
|
|
598
|
+
data: true,
|
|
599
|
+
originalIndex: dataId,
|
|
600
|
+
layoutInfo: null
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
await this.createCards({ end: 0, dataId })
|
|
604
|
+
|
|
605
|
+
index += 1;
|
|
606
|
+
|
|
607
|
+
}
|
|
608
|
+
// options.data.forEach((item, index) => {
|
|
609
|
+
// const dataId = index; // this.nextDataId++;
|
|
610
|
+
// if (!this.allReadyNodes.has(dataId)) {
|
|
611
|
+
// this.dataIdMap.set(dataId, {
|
|
612
|
+
// data: true,// item,
|
|
613
|
+
// originalIndex: index,
|
|
614
|
+
// layoutInfo: null // 将在布局时填充
|
|
615
|
+
// });
|
|
616
|
+
// // 如果没有准备好这个数据,这里要创建一个占位节点
|
|
617
|
+
// this.createCards({ end: 0, dataId });
|
|
618
|
+
// }
|
|
619
|
+
// });
|
|
620
|
+
|
|
621
|
+
// this.updateVisibleItems(true); // 强制更新渲染
|
|
622
|
+
|
|
590
623
|
|
|
591
|
-
// 重新计算所有卡片位置并更新位置
|
|
592
|
-
// this.updatePointCards();
|
|
593
624
|
}
|
|
594
625
|
|
|
595
626
|
// 某个数据进行了UI变更,触发高度重新绘制
|
|
@@ -701,7 +732,6 @@ Waterfall.prototype.updatePointCards = function () {
|
|
|
701
732
|
Waterfall.prototype.showLoading = function (callback = null) {
|
|
702
733
|
this.isShowLoading = true;
|
|
703
734
|
const options = this.options;
|
|
704
|
-
const $container = $(options.container);
|
|
705
735
|
let $node = null
|
|
706
736
|
if (this.$loadingNode) {
|
|
707
737
|
let loadingTop = this.getMaxHeight() + options.rowGap
|
|
@@ -717,7 +747,6 @@ Waterfall.prototype.showLoading = function (callback = null) {
|
|
|
717
747
|
Waterfall.prototype.hideLoading = function (callback = null) {
|
|
718
748
|
this.isShowLoading = false;
|
|
719
749
|
const options = this.options;
|
|
720
|
-
const $container = $(options.container);
|
|
721
750
|
let $node = null
|
|
722
751
|
if (this.$loadingNode) {
|
|
723
752
|
let h1 = this.getMaxHeight() + options.marginBottom
|
|
@@ -725,14 +754,6 @@ Waterfall.prototype.hideLoading = function (callback = null) {
|
|
|
725
754
|
//如果要设置高度,那么这里判断一下当前是否正在做updata 一般这里被调用时,数据已经读到,在updata的同一时间调用了该函数
|
|
726
755
|
// 如果两个时刻高度是一致的 那么数据就是一致的 这里重新设置回来高度即可
|
|
727
756
|
window.requestAnimationFrame(() => {
|
|
728
|
-
// let h2 = this.getMaxHeight() + options.marginBottom
|
|
729
|
-
// if (h1 === h2) {
|
|
730
|
-
// const $scroll = $(options.container).find('.waterfall-list-scroll')
|
|
731
|
-
// const h = $scroll.height()
|
|
732
|
-
// if (h !== h1) {
|
|
733
|
-
// $scroll.css('height', h1 + 'px');
|
|
734
|
-
// }
|
|
735
|
-
// }
|
|
736
757
|
this.setScrollHeight();
|
|
737
758
|
})
|
|
738
759
|
$node = this.$loadingNode
|