tencent.jquery.pix.component 1.0.64 → 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.
@@ -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, // 滚动事件回调函数
@@ -42,6 +43,8 @@ export function Waterfall(optionsInput = {}) {
42
43
 
43
44
  this.$loadingNode = null;
44
45
 
46
+ this.isShowLoading = false; // 是否展示loading
47
+
45
48
 
46
49
  // 间隔字符串转数字
47
50
  if (options.columnGap.constructor === String) {
@@ -125,6 +128,7 @@ Waterfall.prototype.init = function () {
125
128
  const self = this;
126
129
  const options = this.options;
127
130
  const $container = $(options.container);
131
+ const $scrollDom = options.scrollDom ? $(options.scrollDom) : $container;
128
132
 
129
133
  this.nodePool = []; // DOM 节点池
130
134
  this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
@@ -140,6 +144,7 @@ Waterfall.prototype.init = function () {
140
144
 
141
145
 
142
146
  // 如果有定义loading函数 那么创建一个loading节点元素
147
+ console.log('options.createLoading', options.createLoading)
143
148
  if (options.createLoading) {
144
149
  this.$loadingNode = $(
145
150
  `<div class="waterfall-loading" style="transform: translate(0px, -99999px)"></div>`
@@ -150,7 +155,7 @@ Waterfall.prototype.init = function () {
150
155
  }
151
156
 
152
157
  // 绑定滚动事件(节流处理)
153
- $container.off().on('scroll', function () {
158
+ $scrollDom.off().on('scroll', function () {
154
159
  self.scrollTop = $(this).scrollTop();
155
160
 
156
161
  window.requestAnimationFrame(() => {
@@ -162,7 +167,7 @@ Waterfall.prototype.init = function () {
162
167
  }
163
168
  });
164
169
 
165
- this.scrollTop = $container.scrollTop(); // 当前滚动位置
170
+ this.scrollTop = $scrollDom.scrollTop(); // 当前滚动位置
166
171
 
167
172
  // 首次渲染
168
173
  self.updateVisibleItems();
@@ -173,11 +178,17 @@ Waterfall.prototype.init = function () {
173
178
  Waterfall.prototype.updateVisibleItems = function (force = false) {
174
179
  const self = this;
175
180
  const options = this.options;
176
- const $container = $(options.container);
181
+ let h = 0;
182
+ if (options.scrollDom) {
183
+ h = $(options.scrollDom).height();
184
+ } else {
185
+ h = $(options.container).height();
186
+ }
177
187
 
178
188
  const startTop = self.scrollTop; // 当前滚动位置
179
- const endTop = startTop + $container.height();
189
+ const endTop = startTop + h;
180
190
  // console.log('startTop', startTop)
191
+ console.log('endTop', endTop)
181
192
 
182
193
  // 进行可见区域的渲染更新
183
194
  this.updateCardsInView({
@@ -228,13 +239,13 @@ Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
228
239
  }
229
240
 
230
241
  // 获取指定高度下的卡片索引
231
- Waterfall.prototype.updateCardsInView = function ({ start, end, force = false }) {
242
+ Waterfall.prototype.updateCardsInView = async function ({ start, end, force = false }) {
232
243
  const options = this.options;
233
244
  const minHeight = this.getMinHeight();
234
245
  const endBuffer = end + options.bufferHeight;
235
246
  if (minHeight < endBuffer) {
236
247
  // 如果不够 进行补建
237
- this.createCards({ end: endBuffer });
248
+ await this.createCards({ end: endBuffer });
238
249
  }
239
250
 
240
251
  const startNum = start - options.bufferHeight;
@@ -400,123 +411,125 @@ Waterfall.prototype.getMinHeightColumn = function () {
400
411
  }
401
412
 
402
413
  // 创建卡片
403
- Waterfall.prototype.createCards = function ({ end, dataId = -1 }) {
414
+ Waterfall.prototype.createCards = function ({ end, dataId = -1 }, callback) {
404
415
  const self = this;
405
416
  const options = this.options;
406
- const $container = $(options.container);
407
417
 
408
- // 新方案:获取下一个未渲染的数据ID
409
- let nextDataId = null;
410
- for (let [dataId, dataInfo] of this.dataIdMap) {
411
- if (!this.renderedDataIds.has(dataId)) {
412
- nextDataId = dataId;
413
- break;
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
+ }
414
426
  }
415
- }
416
427
 
417
428
 
418
- // 如果没有更多数据需要渲染
419
- if (nextDataId === null) {
420
- const maxHeight = this.getMaxHeight();
421
- $container.find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
422
- return;
423
- }
424
-
425
- const dataInfo = this.dataIdMap.get(nextDataId);
426
- if (!dataInfo || !dataInfo.data) {
427
- console.warn('Waterfall: Invalid data for dataId', nextDataId);
428
- return;
429
- }
429
+ // 如果没有更多数据需要渲染
430
+ if (nextDataId === null) {
431
+ this.setScrollHeight();
432
+ return resolve();
433
+ }
430
434
 
431
- if (this.renderIndex >= options.data.length) {
432
- const maxHeight = this.getMaxHeight();
433
- $container.find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
434
- return
435
- }
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
+ }
436
440
 
437
- const data = options.data[nextDataId];
441
+ if (this.renderIndex >= options.data.length) {
442
+ this.setScrollHeight();
443
+ return resolve();
444
+ }
438
445
 
439
- let column = this.getMinHeightColumn();
440
- if (column === null) {
441
- column = this.columnItems[0];
442
- }
446
+ const data = options.data[nextDataId];
443
447
 
444
- const top = column.bottom === 0 ? options.marginTop : (column.bottom + options.rowGap);
445
- const position = { top, left: column.left };
446
- const row = createDefaultRow(position);
448
+ let column = this.getMinHeightColumn();
449
+ if (column === null) {
450
+ column = this.columnItems[0];
451
+ }
447
452
 
448
- this.renderIndex += 1;
453
+ const top = column.bottom === 0 ? options.marginTop : (column.bottom + options.rowGap);
454
+ const position = { top, left: column.left };
455
+ const row = createDefaultRow(position);
449
456
 
450
- let specialNode = false;
457
+ this.renderIndex += 1;
451
458
 
452
- // 如果是特殊的卡片,需要指定节点不变更的数据,那么该数据的节点不能被其他数据使用
453
- if (options.shouldOccupySpace) {
454
- specialNode = options.shouldOccupySpace(data) || false;
455
- }
459
+ let specialNode = false;
456
460
 
457
- // 添加卡片,使用dataId作为唯一标识
458
- let $card = null;
459
- if (this.nodePool.length === 0 || specialNode === true) {
460
- $card = this.appendCard(data, nextDataId, position);
461
- } else {
462
- const $tmp = getNodePoolPop(this.nodePool, this.activeNodes);
463
- if ($tmp) {
464
- $card = $tmp;
465
- $card.css({
466
- 'transform': `translate(${row.left}px,${row.top}px)`,
467
- }).attr('data-index', nextDataId);
468
- this.updateRenderUI($card, data, nextDataId);
469
- } else {
470
- $card = this.appendCard(data, nextDataId, position);
461
+ // 如果是特殊的卡片,需要指定节点不变更的数据,那么该数据的节点不能被其他数据使用
462
+ if (options.shouldOccupySpace) {
463
+ specialNode = options.shouldOccupySpace(data) || false;
471
464
  }
472
465
 
473
- }
474
-
475
- row.$node = $card;
476
- row.dataId = nextDataId; // 使用dataId替代renderIndex
477
- if (dataId !== -1) {
478
- row.dataId = dataId;
479
- }
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
+ }
480
481
 
481
- // 记录布局信息
482
- // dataInfo.layoutInfo = {
483
- // //columnIndex: this.columnItems.indexOf(column),
484
- // //position: position,
485
- // // row: row
486
- // };
482
+ }
487
483
 
484
+ row.$node = $card;
485
+ row.dataId = nextDataId; // 使用dataId替代renderIndex
486
+ if (dataId !== -1) {
487
+ row.dataId = dataId;
488
+ }
488
489
 
490
+ if (specialNode === false) {
491
+ // 把新增的卡片放进 activeNodes 当成活跃节点元素,那么是 可以动态使用的
492
+ this.activeNodes.set(nextDataId, $card);
489
493
 
494
+ this.allReadyNodes.set(nextDataId, $card);
495
+ } else {
496
+ // 如果是特殊的,这里不要记录了
497
+ this.allReadyNodes.set(nextDataId, null);
498
+ }
490
499
 
491
- if (specialNode === false) {
492
- // 把新增的卡片放进 activeNodes 当成活跃节点元素,那么是 可以动态使用的
493
- this.activeNodes.set(nextDataId, $card);
500
+ this.renderedDataIds.add(nextDataId);
494
501
 
495
- this.allReadyNodes.set(nextDataId, $card);
496
- } else {
497
- // 如果是特殊的,这里不要记录了
498
- this.allReadyNodes.set(nextDataId, null);
499
- }
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;
500
509
 
501
- this.renderedDataIds.add(nextDataId);
510
+ // 检查是否需要继续创建卡片
511
+ const minHeight = this.getMinHeight();
512
+ const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
502
513
 
503
- // 更新列的底部距离
504
- column.bottom = top + $card.height();
505
- column.children.push(row);
506
- row.bottom = column.bottom;
514
+ if (hasMoreData && (minHeight < end)) {
507
515
 
508
- // 检查是否需要继续创建卡片
509
- const minHeight = this.getMinHeight();
510
- const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
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
+ });
511
532
 
512
- if (hasMoreData && (minHeight < end)) {
513
- window.requestAnimationFrame(() => {
514
- this.createCards({ end });
515
- });
516
- } else {
517
- const maxHeight = this.getMaxHeight();
518
- $(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
519
- }
520
533
  }
521
534
 
522
535
 
@@ -559,7 +572,7 @@ Waterfall.prototype.updateRenderUI = function ($node, data, dataId) {
559
572
 
560
573
 
561
574
 
562
- Waterfall.prototype.updateData = function (newData) {
575
+ Waterfall.prototype.updateData = async function (newData) {
563
576
  const options = this.options;
564
577
  options.data = newData;
565
578
 
@@ -569,23 +582,45 @@ Waterfall.prototype.updateData = function (newData) {
569
582
  //this.nextDataId = 0;
570
583
 
571
584
  // 为每个数据项分配唯一ID
572
- options.data.forEach((item, index) => {
573
- const dataId = index; // this.nextDataId++;
574
- if (!this.allReadyNodes.has(dataId)) {
575
- this.dataIdMap.set(dataId, {
576
- data: true,// item,
577
- originalIndex: index,
578
- layoutInfo: null // 将在布局时填充
579
- });
580
- // 如果没有准备好这个数据,这里要创建一个占位节点
581
- 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;
582
594
  }
583
- });
584
595
 
585
- this.updateVisibleItems(true); // 强制更新渲染
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
+
586
623
 
587
- // 重新计算所有卡片位置并更新位置
588
- // this.updatePointCards();
589
624
  }
590
625
 
591
626
  // 某个数据进行了UI变更,触发高度重新绘制
@@ -695,26 +730,23 @@ Waterfall.prototype.updatePointCards = function () {
695
730
 
696
731
  // 展示loading的回调函数
697
732
  Waterfall.prototype.showLoading = function (callback = null) {
733
+ this.isShowLoading = true;
698
734
  const options = this.options;
699
- const $container = $(options.container);
700
735
  let $node = null
701
736
  if (this.$loadingNode) {
702
737
  let loadingTop = this.getMaxHeight() + options.rowGap
703
- let h = loadingTop + this.$loadingNode.height() + options.marginBottom
704
-
705
738
  this.$loadingNode.css('transform', `translate(0px,${loadingTop}px)`);
706
- $(options.container).find('.waterfall-list-scroll').css('height', h + 'px');
707
-
708
739
  $node = this.$loadingNode
709
740
  }
710
741
 
711
742
  if (callback) callback($node)
743
+ this.setScrollHeight();
712
744
  }
713
745
 
714
746
  // 隐藏loading的回调函数
715
747
  Waterfall.prototype.hideLoading = function (callback = null) {
748
+ this.isShowLoading = false;
716
749
  const options = this.options;
717
- const $container = $(options.container);
718
750
  let $node = null
719
751
  if (this.$loadingNode) {
720
752
  let h1 = this.getMaxHeight() + options.marginBottom
@@ -722,19 +754,27 @@ Waterfall.prototype.hideLoading = function (callback = null) {
722
754
  //如果要设置高度,那么这里判断一下当前是否正在做updata 一般这里被调用时,数据已经读到,在updata的同一时间调用了该函数
723
755
  // 如果两个时刻高度是一致的 那么数据就是一致的 这里重新设置回来高度即可
724
756
  window.requestAnimationFrame(() => {
725
- let h2 = this.getMaxHeight() + options.marginBottom
726
- if (h1 === h2) {
727
- const $scroll = $(options.container).find('.waterfall-list-scroll')
728
- const h = $scroll.height()
729
- if (h !== h1) {
730
- $scroll.css('height', h1 + 'px');
731
- }
732
- }
757
+ this.setScrollHeight();
733
758
  })
734
759
  $node = this.$loadingNode
735
760
  }
736
761
 
737
762
  if (callback) callback($node)
763
+ this.setScrollHeight();
764
+ }
765
+
766
+ // 设置滚动条列表的高度
767
+ Waterfall.prototype.setScrollHeight = function () {
768
+ const options = this.options;
769
+ const $container = $(options.container);
770
+ let h = this.getMaxHeight();
771
+ if (this.isShowLoading === true) {
772
+ if (this.$loadingNode) {
773
+ h += options.rowGap + this.$loadingNode.height();
774
+ }
775
+ }
776
+ h += options.marginBottom;
777
+ $container.find('.waterfall-list-scroll').css('height', h + 'px');
738
778
  }
739
779
 
740
780
  function createDefaultRow({ top, left }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tencent.jquery.pix.component",
3
- "version": "1.0.64",
3
+ "version": "1.0.66-beta1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "files": [