From b64e854a09ebb8273da259a69000af1baac224da Mon Sep 17 00:00:00 2001 From: ryuever Date: Sun, 25 Jun 2023 00:48:17 +0800 Subject: [PATCH] feat: close #30 (#32) --- packages/data-model/src/BaseLayout.ts | 24 +++++++++++++++++-- packages/data-model/src/ItemsDimensions.ts | 9 ++++--- packages/data-model/src/ListDimensions.ts | 17 +++++++++---- .../data-model/src/PseudoListDimensions.ts | 13 ++++++---- packages/data-model/src/common.ts | 1 + .../data-model/src/types/Dimensions.types.ts | 2 ++ 6 files changed, 53 insertions(+), 13 deletions(-) diff --git a/packages/data-model/src/BaseLayout.ts b/packages/data-model/src/BaseLayout.ts index 8b1bd115..63fff480 100644 --- a/packages/data-model/src/BaseLayout.ts +++ b/packages/data-model/src/BaseLayout.ts @@ -5,6 +5,7 @@ import { ON_END_REACHED_THRESHOLD, WINDOW_SIZE, RECYCLE_BUFFERED_COUNT, + LENGTH_PRECISION, } from './common'; import SelectValue, { selectHorizontalValue, @@ -28,6 +29,7 @@ class BaseLayout { private _recycleThreshold: number; readonly _onEndReachedThreshold: number; readonly _fillingMode: FillingMode; + readonly _lengthPrecision: number; private _recycleBufferedCount: number; private _canIUseRIC: boolean; @@ -47,6 +49,8 @@ class BaseLayout { recycleEnabled?: boolean; canIUseRIC?: boolean; + + lengthPrecision?: number; }) { const { id, @@ -58,6 +62,7 @@ class BaseLayout { canIUseRIC, stickyHeaderIndices = [], windowSize = WINDOW_SIZE, + lengthPrecision = LENGTH_PRECISION, recycleBufferedCount = RECYCLE_BUFFERED_COUNT, maxToRenderPerBatch = MAX_TO_RENDER_PER_BATCH, initialNumToRender = INITIAL_NUM_TO_RENDER, @@ -77,15 +82,17 @@ class BaseLayout { this._recycleThreshold = recycleEnabled ? recycleThreshold || maxToRenderPerBatch * 2 : 0; - this._recycleBufferedCount = recycleBufferedCount; + + // recycleBufferedCount should greater than 0. + this._recycleBufferedCount = Math.max(recycleBufferedCount, 1); this._stickyHeaderIndices = stickyHeaderIndices; this._maxToRenderPerBatch = maxToRenderPerBatch; this._initialNumToRender = initialNumToRender; this._onEndReachedThreshold = onEndReachedThreshold; - this._recycleBufferedCount = recycleBufferedCount; this.persistanceIndices = persistanceIndices; this.stickyHeaderIndices = stickyHeaderIndices; this._canIUseRIC = canIUseRIC; + this._lengthPrecision = lengthPrecision; } get initialNumToRender() { @@ -228,6 +235,19 @@ class BaseLayout { getSelectValue() { return this._selectValue; } + + normalizeLengthNumber(length: number) { + return +length.toPrecision(this._lengthPrecision); + } + + normalizeLengthInfo(info: ItemLayout) { + const { width, height, ...rest } = info; + return { + width: this.normalizeLengthNumber(width), + height: this.normalizeLengthNumber(height), + ...rest, + }; + } } export default BaseLayout; diff --git a/packages/data-model/src/ItemsDimensions.ts b/packages/data-model/src/ItemsDimensions.ts index 56c981c5..cc22aac2 100644 --- a/packages/data-model/src/ItemsDimensions.ts +++ b/packages/data-model/src/ItemsDimensions.ts @@ -37,16 +37,19 @@ class ItemsDimensions extends BaseDimensions { if (!meta) return false; if (typeof info === 'number') { - const length = info; + const length = this.normalizeLengthNumber(info); if (this._selectValue.selectLength(meta.getLayout()) !== length) { this._selectValue.setLength(meta.getLayout(), length); this._sortedItems.add(meta); return true; } + return false; } - if (!layoutEqual(meta.getLayout(), info as ItemLayout)) { - meta.setLayout(info as ItemLayout); + const _info = this.normalizeLengthInfo(info); + + if (!layoutEqual(meta.getLayout(), _info as ItemLayout)) { + meta.setLayout(_info as ItemLayout); this._sortedItems.add(meta); return true; } diff --git a/packages/data-model/src/ListDimensions.ts b/packages/data-model/src/ListDimensions.ts index 4d1c9360..efd30df3 100644 --- a/packages/data-model/src/ListDimensions.ts +++ b/packages/data-model/src/ListDimensions.ts @@ -856,7 +856,7 @@ class ListDimensions extends BaseDimensions { if (!meta) return false; if (typeof info === 'number') { - let length = info; + let length = this.normalizeLengthNumber(info); if (this._selectValue.selectLength(meta.getLayout() || {}) !== length) { this._selectValue.setLength(meta.ensureLayout(), length); @@ -868,14 +868,23 @@ class ListDimensions extends BaseDimensions { return true; } } + return false; } + const _info = this.normalizeLengthInfo(info); + + if (!layoutEqual(meta.getLayout(), _info as ItemLayout)) { + if (meta.getLayout()) { + console.warn( + '[infinite-list/data-model] override existing key item ', + `${+key}from value ${meta.getLayout()}to ${_info}` + ); + } - if (!layoutEqual(meta.getLayout(), info as ItemLayout)) { const currentLength = this._selectValue.selectLength( meta.getLayout() || {} ); - let length = this._selectValue.selectLength((info as ItemLayout) || {}); - meta.setLayout(info as ItemLayout); + let length = this._selectValue.selectLength((_info as ItemLayout) || {}); + meta.setLayout(_info as ItemLayout); // 只有关心的值发生变化时,才会再次触发setIntervalTreeValue if (currentLength !== length && _update) { if (index !== this._data.length - 1) { diff --git a/packages/data-model/src/PseudoListDimensions.ts b/packages/data-model/src/PseudoListDimensions.ts index cea67cc5..9d129976 100644 --- a/packages/data-model/src/PseudoListDimensions.ts +++ b/packages/data-model/src/PseudoListDimensions.ts @@ -140,7 +140,7 @@ class PseudoListDimensions extends BaseDimensions { if (!meta) return false; if (typeof info === 'number') { - const length = info; + const length = this.normalizeLengthNumber(info); if (meta && this._selectValue.selectLength(meta.getLayout()) !== length) { this._selectValue.setLength(meta.getLayout(), length); if (_update) { @@ -148,14 +148,19 @@ class PseudoListDimensions extends BaseDimensions { return true; } } + return false; } - if (!layoutEqual(meta.getLayout(), info as ItemLayout)) { + const _info = this.normalizeLengthInfo(info); + + if (!layoutEqual(meta.getLayout(), _info as ItemLayout)) { const currentLength = this._selectValue.selectLength( meta.getLayout() || {} ); - const length = this._selectValue.selectLength((info as ItemLayout) || {}); - meta.setLayout(info as ItemLayout); + const length = this._selectValue.selectLength( + (_info as ItemLayout) || {} + ); + meta.setLayout(_info as ItemLayout); if (currentLength !== length && _update) { this.setIntervalTreeValue(index, length); diff --git a/packages/data-model/src/common.ts b/packages/data-model/src/common.ts index e57ff049..639a571b 100644 --- a/packages/data-model/src/common.ts +++ b/packages/data-model/src/common.ts @@ -10,6 +10,7 @@ export const ON_END_REACHED_TIMEOUT_THRESHOLD = 200; export const ON_END_REACHED_HANDLER_TIMEOUT_THRESHOLD = 2000; export const DISPATCH_METRICS_THRESHOLD = 50; export const RECYCLE_BUFFERED_COUNT = 4; +export const LENGTH_PRECISION = 4; // 建议 ON_END_REACHED_THRESHOLD * VisibleLength > MAX_TO_RENDER_PER_BATCH * itemLength // 这样可以在滚动停止的时候,自动获取一屏幕 diff --git a/packages/data-model/src/types/Dimensions.types.ts b/packages/data-model/src/types/Dimensions.types.ts index 0d118205..34219440 100644 --- a/packages/data-model/src/types/Dimensions.types.ts +++ b/packages/data-model/src/types/Dimensions.types.ts @@ -27,6 +27,8 @@ export type BaseDimensionsProps = { canIUseRIC?: boolean; + lengthPrecision?: number; + onUpdateItemLayout?: Function; onUpdateIntervalTree?: Function; isIntervalTreeItems?: boolean;