@tarojs/components-advanced 4.1.12-beta.0 → 4.1.12-beta.10

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.
Files changed (72) hide show
  1. package/dist/components/index.js +2 -0
  2. package/dist/components/index.js.map +1 -1
  3. package/dist/components/list/NoMore.d.ts +30 -0
  4. package/dist/components/list/NoMore.js +10 -0
  5. package/dist/components/list/NoMore.js.map +1 -0
  6. package/dist/components/list/hooks/useItemSizeCache.d.ts +13 -0
  7. package/dist/components/list/hooks/useItemSizeCache.js +40 -0
  8. package/dist/components/list/hooks/useItemSizeCache.js.map +1 -0
  9. package/dist/components/list/hooks/useListNestedScroll.d.ts +18 -0
  10. package/dist/components/list/hooks/useListNestedScroll.js +61 -0
  11. package/dist/components/list/hooks/useListNestedScroll.js.map +1 -0
  12. package/dist/components/list/hooks/useListScrollElementAttach.d.ts +21 -0
  13. package/dist/components/list/hooks/useListScrollElementAttach.js +86 -0
  14. package/dist/components/list/hooks/useListScrollElementAttach.js.map +1 -0
  15. package/dist/components/list/hooks/useListScrollElementAttachWeapp.d.ts +27 -0
  16. package/dist/components/list/hooks/useListScrollElementAttachWeapp.js +154 -0
  17. package/dist/components/list/hooks/useListScrollElementAttachWeapp.js.map +1 -0
  18. package/dist/components/list/hooks/useMeasureStartOffset.d.ts +12 -0
  19. package/dist/components/list/hooks/useMeasureStartOffset.js +84 -0
  20. package/dist/components/list/hooks/useMeasureStartOffset.js.map +1 -0
  21. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.d.ts +13 -0
  22. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js +85 -0
  23. package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js.map +1 -0
  24. package/dist/components/list/hooks/useRefresher.d.ts +74 -0
  25. package/dist/components/list/hooks/useRefresher.js +503 -0
  26. package/dist/components/list/hooks/useRefresher.js.map +1 -0
  27. package/dist/components/list/hooks/useResizeObserver.d.ts +26 -0
  28. package/dist/components/list/hooks/useResizeObserver.js +152 -0
  29. package/dist/components/list/hooks/useResizeObserver.js.map +1 -0
  30. package/dist/components/list/hooks/useScrollCorrection.d.ts +19 -0
  31. package/dist/components/list/hooks/useScrollCorrection.js +73 -0
  32. package/dist/components/list/hooks/useScrollCorrection.js.map +1 -0
  33. package/dist/components/list/hooks/useScrollParentAutoFind.d.ts +20 -0
  34. package/dist/components/list/hooks/useScrollParentAutoFind.js +81 -0
  35. package/dist/components/list/hooks/useScrollParentAutoFind.js.map +1 -0
  36. package/dist/components/list/index.d.ts +59 -3
  37. package/dist/components/list/index.js +997 -119
  38. package/dist/components/list/index.js.map +1 -1
  39. package/dist/components/list/utils.d.ts +16 -0
  40. package/dist/components/list/utils.js +19 -0
  41. package/dist/components/list/utils.js.map +1 -0
  42. package/dist/components/virtual-list/vue/list.d.ts +12 -12
  43. package/dist/components/virtual-waterfall/vue/waterfall.d.ts +11 -11
  44. package/dist/components/water-flow/flow-item.js +6 -4
  45. package/dist/components/water-flow/flow-item.js.map +1 -1
  46. package/dist/components/water-flow/flow-section.js +1 -1
  47. package/dist/components/water-flow/flow-section.js.map +1 -1
  48. package/dist/components/water-flow/interface.d.ts +14 -2
  49. package/dist/components/water-flow/root.d.ts +16 -2
  50. package/dist/components/water-flow/root.js +70 -28
  51. package/dist/components/water-flow/root.js.map +1 -1
  52. package/dist/components/water-flow/section.d.ts +1 -1
  53. package/dist/components/water-flow/section.js +12 -4
  54. package/dist/components/water-flow/section.js.map +1 -1
  55. package/dist/components/water-flow/utils.d.ts +4 -0
  56. package/dist/components/water-flow/utils.js +5 -1
  57. package/dist/components/water-flow/utils.js.map +1 -1
  58. package/dist/components/water-flow/water-flow.d.ts +1 -1
  59. package/dist/components/water-flow/water-flow.js +248 -27
  60. package/dist/components/water-flow/water-flow.js.map +1 -1
  61. package/dist/index.js +3 -0
  62. package/dist/index.js.map +1 -1
  63. package/dist/utils/index.d.ts +1 -0
  64. package/dist/utils/index.js +1 -0
  65. package/dist/utils/index.js.map +1 -1
  66. package/dist/utils/scrollElementContext.d.ts +15 -0
  67. package/dist/utils/scrollElementContext.js +14 -0
  68. package/dist/utils/scrollElementContext.js.map +1 -0
  69. package/dist/utils/scrollParent.d.ts +33 -0
  70. package/dist/utils/scrollParent.js +88 -0
  71. package/dist/utils/scrollParent.js.map +1 -0
  72. package/package.json +9 -8
@@ -1 +1 @@
1
- {"version":3,"file":"flow-section.js","sources":["../../../src/components/water-flow/flow-section.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n Children,\n createElement,\n useMemo,\n} from 'react'\n\nimport { FlowItemContainer } from './flow-item'\nimport { Section } from './section'\nimport { useObservedAttr } from './use-observed-attr'\n\nimport type { FlowSectionProps } from './interface'\n\nexport interface _FlowSectionProps extends FlowSectionProps {\n section: Section\n}\n\nexport function FlowSection({\n children,\n ...props\n}: PropsWithChildren<FlowSectionProps>) {\n const {\n id,\n className,\n style,\n section,\n rowGap = 0,\n columnGap = 0,\n } = props as _FlowSectionProps\n const layouted$ = useObservedAttr(section, 'layouted')\n const height$ = useObservedAttr(section, 'height')\n const renderRange$ = useObservedAttr(section, 'renderRange')\n const scrollTop$ = useObservedAttr(section, 'scrollTop')\n\n const sectionStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n width: '100%',\n height: height$,\n gap: columnGap,\n visibility: layouted$ ? 'visible' : 'hidden',\n ...style,\n }\n\n if (!layouted$) {\n return baseStyle\n }\n\n return {\n ...baseStyle,\n position: 'absolute',\n top: 0,\n transform: `translate3d(0px, ${scrollTop$}px, 0px)`,\n left: 0,\n }\n }, [height$, style, layouted$, scrollTop$, columnGap])\n\n const columns = useMemo(() => {\n const childNodes = Children.toArray(children)\n const columnStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: rowGap,\n flex: 1,\n }\n /** 已经完成布局计算,使用虚拟滚动 */\n if (layouted$) {\n return renderRange$.map(([startIndex, endIndex], colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n {\n style: columnStyle,\n id: columnId,\n key: columnId,\n },\n section.columnMap[colIndex]\n .slice(startIndex, endIndex + 1)\n .map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }\n\n return section.columnMap.map((column, colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n { style: columnStyle, id: columnId, key: columnId },\n column.map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }, [children, layouted$, section.columnMap, renderRange$, id])\n\n return createElement(\n View,\n { style: sectionStyle, className, id: id ?? section.id },\n columns\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow-section.js","sources":["../../../src/components/water-flow/flow-section.ts"],"sourcesContent":["import { View } from '@tarojs/components'\nimport {\n type CSSProperties,\n type PropsWithChildren,\n Children,\n createElement,\n useMemo,\n} from 'react'\n\nimport { FlowItemContainer } from './flow-item'\nimport { Section } from './section'\nimport { useObservedAttr } from './use-observed-attr'\n\nimport type { FlowSectionProps } from './interface'\n\nexport interface _FlowSectionProps extends FlowSectionProps {\n section: Section\n}\n\nexport function FlowSection({\n children,\n ...props\n}: PropsWithChildren<FlowSectionProps>) {\n const {\n id,\n className,\n style,\n section,\n rowGap = 0,\n columnGap = 0,\n } = props as _FlowSectionProps\n const layouted$ = useObservedAttr(section, 'layouted')\n const height$ = useObservedAttr(section, 'height')\n const renderRange$ = useObservedAttr(section, 'renderRange')\n const scrollTop$ = useObservedAttr(section, 'scrollTop')\n\n const sectionStyle: CSSProperties = useMemo(() => {\n const baseStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'row',\n width: '100%',\n height: height$,\n gap: columnGap,\n visibility: layouted$ ? 'visible' : 'hidden',\n ...style,\n }\n\n if (!layouted$) {\n return baseStyle\n }\n\n return {\n ...baseStyle,\n position: 'absolute',\n top: 0,\n transform: `translate3d(0px, ${scrollTop$}px, 0px)`,\n left: 0,\n }\n }, [height$, style, layouted$, scrollTop$, columnGap])\n\n const columns = useMemo(() => {\n const childNodes = Children.toArray(children)\n const columnStyle: CSSProperties = {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n gap: rowGap,\n flex: 1,\n }\n /** 已经完成布局计算,使用虚拟滚动 */\n if (layouted$) {\n return renderRange$.map(([startIndex, endIndex], colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n {\n style: columnStyle,\n id: columnId,\n key: columnId,\n },\n section.columnMap[colIndex]\n .slice(startIndex, endIndex + 1)\n .map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }\n\n return section.columnMap.map((column, colIndex) => {\n const columnId = `col-${colIndex}`\n return createElement(\n View,\n { style: columnStyle, id: columnId, key: columnId },\n column.map((node) => {\n const childNode = childNodes[node.childIndex]\n const columnProps: any = {\n node,\n key: node.id,\n }\n return createElement(FlowItemContainer, columnProps, childNode)\n })\n )\n })\n }, [children, layouted$, section.columnMap, renderRange$])\n\n return createElement(\n View,\n { style: sectionStyle, className, id: id ?? section.id },\n columns\n )\n}\n"],"names":[],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { ScrollViewProps } from '@tarojs/components';
2
2
  import { Node } from './node';
3
- import type { CSSProperties } from 'react';
3
+ import type { CSSProperties, RefObject } from 'react';
4
4
  export interface BaseProps {
5
5
  id?: string;
6
6
  className?: string;
7
7
  style?: CSSProperties;
8
8
  }
9
- export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'upperThreshold' | 'lowerThreshold' | 'style'>, Pick<BaseProps, 'style'> {
9
+ export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'upperThreshold' | 'lowerThreshold' | 'style' | 'type'>, Pick<BaseProps, 'style'> {
10
10
  /**
11
11
  * 距顶部多少个FlowItem时,触发 scrolltoupper 事件
12
12
  * @default 0
@@ -22,6 +22,18 @@ export interface WaterFlowProps extends Omit<ScrollViewProps, 'cacheExtent' | 'u
22
22
  * @default 50
23
23
  */
24
24
  cacheCount?: number;
25
+ /** 是否嵌套模式,与 plato 对齐;true=使用父级滚动,需配合 scrollElement 或 Context;不传或 false=default */
26
+ nestedScroll?: boolean;
27
+ /** 自定义滚动容器 ref,nestedScroll 模式下从 props 或 Context 获取 */
28
+ scrollElement?: RefObject<HTMLElement | null>;
29
+ /** WaterFlow 内容在滚动容器中的起始偏移(上方有其他内容时使用) */
30
+ startOffset?: number;
31
+ /** 可视区高度,scrollElement 模式下可选,不传则从 scrollElement.clientHeight 获取 */
32
+ containerHeight?: number;
33
+ /** 瀑布流内容高度变化时回调,便于 List 动高联动(避免底部空白) */
34
+ onScrollHeightChange?: (height: number) => void;
35
+ /** scrollIntoView 滚动完成后回调,便于父组件清空 scrollIntoView 以支持重复点击同一目标 */
36
+ onScrollIntoViewComplete?: () => void;
25
37
  }
26
38
  export interface FlowSectionProps extends BaseProps {
27
39
  /**
@@ -2,7 +2,10 @@ import { Node } from './node';
2
2
  import { Section } from './section';
3
3
  import { StatefulEventBus } from './stateful-event-bus';
4
4
  import type { BaseProps, ScrollDirection, Size, WaterFlowProps } from './interface';
5
- export type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> & Required<Pick<BaseProps, 'id'>>;
5
+ export type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> & Required<Pick<BaseProps, 'id'>> & {
6
+ /** scrollElement 模式下为 true,不测量自有容器;此时需布局全部 section 以展开完整高度 */
7
+ skipContainerMeasure?: boolean;
8
+ };
6
9
  type RootState = {
7
10
  /** 是否在滚动中 */
8
11
  isScrolling: boolean;
@@ -65,6 +68,14 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
65
68
  * 触发滚动阈值对应的 scrollTop 值
66
69
  */
67
70
  lowerThresholdScrollTop: number;
71
+ /** scrollElement 模式下为 true,需布局全部 section 以展开完整高度供父容器滚动 */
72
+ skipContainerMeasure: boolean;
73
+ /** 当前是否处于触顶区域;初始为 true(起始在顶部),只有从 false→true 时才触发事件 */
74
+ private _inUpperZone;
75
+ /** 当前是否处于触底区域;初始为 false */
76
+ private _inLowerZone;
77
+ /** scrollHeight 防抖(raf),避免 pushNodes + 测量 导致的 先涨后跌 闪动 */
78
+ private _scrollHeightRafId;
68
79
  constructor(props: RootProps);
69
80
  /**
70
81
  * 设置订阅事件
@@ -94,6 +105,7 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
94
105
  /**
95
106
  * 处理滚动到阈值的情况
96
107
  * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件
108
+ * scrollElement 模式:scrollOffset 为内容内偏移(scrollTop - startOffset),upper/lowerThresholdScrollTop 基于本组件内容计算,触顶/触底以本 WaterFlow 内容为基准
97
109
  */
98
110
  private handleReachThreshold;
99
111
  /**
@@ -114,8 +126,10 @@ export declare class Root extends StatefulEventBus<RootState, Events> {
114
126
  get sectionRange(): number[][];
115
127
  /**
116
128
  * 计算滚动高度
129
+ * 防抖一帧(raf),避免 pushNodes 后测量完成前出现 先涨(未测量默认高度)后跌(真实高度)导致的闪动
130
+ * @param immediate 为 true 时立即执行,不防抖(pushNodes 调用,避免容器高度滞后导致往上抖动)
117
131
  */
118
- updateScrollHeight(): void;
132
+ updateScrollHeight(immediate?: boolean): void;
119
133
  /**
120
134
  * 注册分组
121
135
  */
@@ -1,3 +1,4 @@
1
+ import { cancelAnimationFrame, requestAnimationFrame } from '@tarojs/runtime';
1
2
  import { nextTick } from '@tarojs/taro';
2
3
  import '../../utils/index.js';
3
4
  import { StatefulEventBus } from './stateful-event-bus.js';
@@ -18,7 +19,7 @@ const RootEvents = {
18
19
  */
19
20
  class Root extends StatefulEventBus {
20
21
  constructor(props) {
21
- const { id, cacheCount, lowerThresholdCount, upperThresholdCount } = props;
22
+ const { id, cacheCount, lowerThresholdCount, upperThresholdCount, skipContainerMeasure } = props;
22
23
  super({
23
24
  isScrolling: false,
24
25
  scrollOffset: 0,
@@ -56,19 +57,30 @@ class Root extends StatefulEventBus {
56
57
  * 触发滚动阈值对应的 scrollTop 值
57
58
  */
58
59
  this.lowerThresholdScrollTop = Infinity;
60
+ /** scrollElement 模式下为 true,需布局全部 section 以展开完整高度供父容器滚动 */
61
+ this.skipContainerMeasure = false;
62
+ /** 当前是否处于触顶区域;初始为 true(起始在顶部),只有从 false→true 时才触发事件 */
63
+ this._inUpperZone = true;
64
+ /** 当前是否处于触底区域;初始为 false */
65
+ this._inLowerZone = false;
66
+ /** scrollHeight 防抖(raf),避免 pushNodes + 测量 导致的 先涨后跌 闪动 */
67
+ this._scrollHeightRafId = null;
59
68
  Object.assign(this, {
60
69
  id,
61
70
  cacheCount,
62
71
  lowerThresholdCount,
63
72
  upperThresholdCount,
73
+ skipContainerMeasure: !!skipContainerMeasure,
64
74
  });
65
75
  this.setupSubscriptions();
66
- getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {
67
- this.setStateIn('containerSize', {
68
- width,
69
- height,
76
+ if (!skipContainerMeasure) {
77
+ getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {
78
+ this.setStateIn('containerSize', {
79
+ width,
80
+ height,
81
+ });
70
82
  });
71
- });
83
+ }
72
84
  this.renderInitialLayout();
73
85
  }
74
86
  /**
@@ -82,22 +94,23 @@ class Root extends StatefulEventBus {
82
94
  this.sub('scrollOffset', () => {
83
95
  this.setStateIn('renderRange', this.getSectionRenderRange());
84
96
  this.handleReachThreshold();
85
- if (this.getState().scrollDirection === 'forward') {
86
- this.updateScrollHeight();
87
- }
97
+ this.updateScrollHeight();
88
98
  });
89
99
  this.sub('scrollOffset', () => {
90
100
  const sectionSize = this.sections.length;
91
101
  const lastSection = this.sections[sectionSize - 1];
92
102
  // 最后一个分组的每一列最后一行都已经完成了布局计算,那么这个时候的总高度应该是准确的
93
- if (lastSection.columnMap.every((column) => column[column.length - 1].getState().layouted)) {
103
+ if (lastSection === null || lastSection === void 0 ? void 0 : lastSection.columnMap.every((column) => { var _a; return (_a = column[column.length - 1]) === null || _a === void 0 ? void 0 : _a.getState().layouted; })) {
94
104
  this.setLowerThresholdScrollTop();
95
105
  }
96
106
  });
97
107
  this.sub(RootEvents.AllSectionsLayouted, () => {
108
+ this.updateScrollHeight();
98
109
  this.setUpperThresholdScrollTop();
110
+ this.setLowerThresholdScrollTop();
99
111
  });
100
112
  this.sub(RootEvents.Resize, () => {
113
+ this.updateScrollHeight();
101
114
  this.setUpperThresholdScrollTop();
102
115
  this.setLowerThresholdScrollTop();
103
116
  });
@@ -122,8 +135,10 @@ class Root extends StatefulEventBus {
122
135
  const section = this.sections[i];
123
136
  section.layoutedSignal.promise.then(() => {
124
137
  this.setStateIn('renderRange', [0, i + 1 > sectionSize ? sectionSize - 1 : i + 1]);
125
- // 容器可视区域已经填满了,没必要再继续
126
- if (section.getState().scrollTop > this.getState().containerSize.height) {
138
+ // skipContainerMeasure(nestedScroll 模式):需布局全部 section,使 scrollHeight 展开供父容器滚动
139
+ // default 模式:容器可视区域已填满则提前终止,减少首屏渲染
140
+ if (!this.skipContainerMeasure &&
141
+ section.getState().scrollTop > this.getState().containerSize.height) {
127
142
  this.pub(RootEvents.InitialRenderCompleted, section);
128
143
  return;
129
144
  }
@@ -189,8 +204,12 @@ class Root extends StatefulEventBus {
189
204
  * 当距底部还有 lowerThresholdCount 个 FlowItem 时的 scrollTop 值
190
205
  */
191
206
  setLowerThresholdScrollTop() {
192
- if (this.lowerThresholdCount === 0) {
193
- this.lowerThresholdScrollTop = this.getState().scrollHeight - this.getState().containerSize.height;
207
+ // setUpperThresholdScrollTop 一致:0 或 undefined 时用「内容底 - 容器高」作为触底阈值
208
+ if (!this.lowerThresholdCount) {
209
+ // 必须用 sectionRange 实时计算,避免依赖可能未更新的 scrollHeight 状态
210
+ const range = this.sectionRange;
211
+ const totalHeight = range.length > 0 ? range[range.length - 1][1] : 0;
212
+ this.lowerThresholdScrollTop = totalHeight - this.getState().containerSize.height;
194
213
  return 0;
195
214
  }
196
215
  const sectionSize = this.sections.length;
@@ -238,20 +257,18 @@ class Root extends StatefulEventBus {
238
257
  /**
239
258
  * 处理滚动到阈值的情况
240
259
  * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件
260
+ * scrollElement 模式:scrollOffset 为内容内偏移(scrollTop - startOffset),upper/lowerThresholdScrollTop 基于本组件内容计算,触顶/触底以本 WaterFlow 内容为基准
241
261
  */
242
262
  handleReachThreshold() {
243
- const { upperThresholdScrollTop } = this;
244
- const { scrollOffset, scrollDirection, containerSize } = this.getState();
245
- if (scrollDirection === 'backward' &&
246
- this.upperThresholdScrollTop !== -Infinity &&
247
- scrollOffset <= upperThresholdScrollTop) {
263
+ const { scrollOffset, containerSize } = this.getState();
264
+ const inUpper = this.upperThresholdScrollTop !== -Infinity && scrollOffset <= this.upperThresholdScrollTop;
265
+ const inLower = this.lowerThresholdScrollTop !== Infinity && scrollOffset + containerSize.height >= this.lowerThresholdScrollTop;
266
+ if (inUpper && !this._inUpperZone)
248
267
  this.pub(RootEvents.ReachUpperThreshold);
249
- }
250
- if (scrollDirection === 'forward' &&
251
- this.lowerThresholdCount !== Infinity &&
252
- scrollOffset + containerSize.height >= this.lowerThresholdScrollTop) {
268
+ if (inLower && !this._inLowerZone)
253
269
  this.pub(RootEvents.ReachLowerThreshold);
254
- }
270
+ this._inUpperZone = inUpper;
271
+ this._inLowerZone = inLower;
255
272
  }
256
273
  /**
257
274
  * 容器的滚动上边界
@@ -273,21 +290,45 @@ class Root extends StatefulEventBus {
273
290
  * @returns [number,number][]
274
291
  */
275
292
  get sectionRange() {
293
+ var _a;
276
294
  const length = this.sections.length;
277
295
  if (length === 0)
278
296
  return [];
279
297
  const range = Array.from({ length }, () => [0, this.sections[0].maxColumnHeight]);
280
298
  for (let i = 1; i < length; i++) {
281
299
  const previous = range[i - 1];
282
- range[i] = [previous[1], previous[1] + this.sections[i].maxColumnHeight];
300
+ const prevSection = this.sections[i - 1];
301
+ const gap = (_a = prevSection.rowGap) !== null && _a !== void 0 ? _a : 0;
302
+ range[i] = [previous[1] + gap, previous[1] + gap + this.sections[i].maxColumnHeight];
283
303
  }
284
304
  return range;
285
305
  }
286
306
  /**
287
307
  * 计算滚动高度
308
+ * 防抖一帧(raf),避免 pushNodes 后测量完成前出现 先涨(未测量默认高度)后跌(真实高度)导致的闪动
309
+ * @param immediate 为 true 时立即执行,不防抖(pushNodes 调用,避免容器高度滞后导致往上抖动)
288
310
  */
289
- updateScrollHeight() {
290
- this.setStateIn('scrollHeight', this.sectionRange[this.sectionRange.length - 1][1]);
311
+ updateScrollHeight(immediate = false) {
312
+ const flush = () => {
313
+ var _a, _b;
314
+ const next = (_b = (_a = this.sectionRange[this.sectionRange.length - 1]) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : 0;
315
+ this.setStateIn('scrollHeight', next);
316
+ };
317
+ if (immediate) {
318
+ if (this._scrollHeightRafId != null) {
319
+ cancelAnimationFrame(this._scrollHeightRafId);
320
+ this._scrollHeightRafId = null;
321
+ }
322
+ flush();
323
+ return;
324
+ }
325
+ if (this._scrollHeightRafId != null) {
326
+ cancelAnimationFrame(this._scrollHeightRafId);
327
+ }
328
+ this._scrollHeightRafId = requestAnimationFrame(() => {
329
+ this._scrollHeightRafId = null;
330
+ flush();
331
+ });
291
332
  }
292
333
  /**
293
334
  * 注册分组
@@ -341,7 +382,8 @@ class Root extends StatefulEventBus {
341
382
  const overscanForward = result[1] + forwardDistance;
342
383
  result[0] = overscanBackward < 0 ? 0 : overscanBackward;
343
384
  result[1] = overscanForward > this.sections.length ? this.sections.length - 1 : overscanForward;
344
- return isSameRenderRange(result, this.getState().renderRange) ? this.getState().renderRange : result;
385
+ const prevRange = this.getState().renderRange;
386
+ return isSameRenderRange(result, prevRange) ? prevRange : result;
345
387
  }
346
388
  /**
347
389
  * 计算预渲染的分组个数
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sources":["../../../src/components/water-flow/root.ts"],"sourcesContent":["/* eslint-disable no-labels */\nimport { nextTick } from '@tarojs/taro'\n\nimport { getRectSizeSync } from '../../utils'\nimport { Node } from './node'\nimport { Section } from './section'\nimport { StatefulEventBus } from './stateful-event-bus'\nimport { getSysInfo, isSameRenderRange } from './utils'\n\nimport type { BaseProps, ScrollDirection, Size, WaterFlowProps } from './interface'\n\nexport type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> &\nRequired<Pick<BaseProps, 'id'>>\n\nconst { windowHeight, windowWidth } = getSysInfo()\n\ntype RootState = {\n /** 是否在滚动中 */\n isScrolling: boolean\n /** 滚动偏移量 */\n scrollOffset: number\n /**\n * 滚动方向\n *\n * - forward 向下滚动\n *\n * - backward 向上滚动\n */\n scrollDirection: ScrollDirection\n /** 滚动高度 */\n scrollHeight: number\n /** 容器的尺寸信息 */\n containerSize: Size\n /** 渲染的分组区间范围 */\n renderRange: [number, number]\n}\n\nexport const RootEvents = {\n ReachUpperThreshold: Symbol.for('ReachUpperThreshold'),\n ReachLowerThreshold: Symbol.for('ReachLowerThreshold'),\n Resize: Symbol.for('Resize'),\n AllSectionsLayouted: Symbol.for('AllSectionsLayouted'),\n InitialRenderCompleted: Symbol.for('InitialRenderCompleted'),\n}\n\ntype Events = keyof typeof RootEvents\n\n/**\n * 数据模型继承自有状态的事件总线,便于在节点之间通信,以及通过 useSyncExternalStore 关联 React 视图\n */\nexport class Root extends StatefulEventBus<RootState, Events> {\n /**\n * 瀑布流根节点唯一标识\n */\n id: string\n /**\n * 分组映射表,便于查找分组\n */\n sectionMap: Map<string, Section> = new Map()\n /**\n * 节点映射表,便于查找节点\n */\n nodeMap: Map<string, Node> = new Map()\n /**\n * 分组列表,基于计算出的渲染的分组区间范围 sections.slice(start, end + 1) 进行渲染\n */\n sections: Section[] = []\n /**\n * 设置预加载的 Item 条数。\n */\n cacheCount = 1\n\n upperThresholdCount = 0\n\n lowerThresholdCount = 0\n\n /**\n * 触发滚动阈值对应的 scrollTop 值\n */\n upperThresholdScrollTop = -Infinity\n\n /**\n * 触发滚动阈值对应的 scrollTop 值\n */\n lowerThresholdScrollTop = Infinity\n\n constructor(props: RootProps) {\n const { id, cacheCount, lowerThresholdCount, upperThresholdCount } = props\n super({\n isScrolling: false,\n scrollOffset: 0,\n scrollDirection: 'forward',\n scrollHeight: windowHeight,\n renderRange: [0, 0],\n containerSize: {\n width: windowWidth,\n height: windowHeight,\n },\n })\n Object.assign(this, {\n id,\n cacheCount,\n lowerThresholdCount,\n upperThresholdCount,\n })\n this.setupSubscriptions()\n getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {\n this.setStateIn('containerSize', {\n width,\n height,\n })\n })\n this.renderInitialLayout()\n }\n\n /**\n * 设置订阅事件\n */\n private setupSubscriptions() {\n /**\n * 滚动过程中计算渲染的分组区间\n * 滚动过程中分组的最大高度会发生更新,可以在这时计算滚动高度\n */\n this.sub('scrollOffset', () => {\n this.setStateIn('renderRange', this.getSectionRenderRange())\n this.handleReachThreshold()\n if (this.getState().scrollDirection === 'forward') {\n this.updateScrollHeight()\n }\n })\n\n this.sub('scrollOffset', () => {\n const sectionSize = this.sections.length\n const lastSection = this.sections[sectionSize - 1]\n // 最后一个分组的每一列最后一行都已经完成了布局计算,那么这个时候的总高度应该是准确的\n if (lastSection.columnMap.every((column) => column[column.length - 1].getState().layouted)) {\n this.setLowerThresholdScrollTop()\n }\n })\n\n this.sub(RootEvents.AllSectionsLayouted, () => {\n this.setUpperThresholdScrollTop()\n })\n\n this.sub(RootEvents.Resize, () => {\n this.setUpperThresholdScrollTop()\n this.setLowerThresholdScrollTop()\n })\n }\n\n /**\n * 渐进式渲染\n *\n * 因为初始没法知道每个分组的高度信息,不知道渲染边界,所以需要渐进式渲染\n *\n * 当目前的渲染批次的首个分组的scrollTop大于容器的高度,说明容器可视区域已经填满,没必要再往下渲染了\n *\n * @param [i=0] 从第几个分组开始渲染\n *\n */\n renderInitialLayout(i = 0) {\n nextTick(() => {\n const sectionSize = this.sections.length\n\n if (i >= sectionSize || i < 0) {\n this.pub(RootEvents.InitialRenderCompleted, null)\n return\n }\n const section = this.sections[i]\n section.layoutedSignal.promise.then(() => {\n this.setStateIn('renderRange', [0, i + 1 > sectionSize ? sectionSize - 1 : i + 1])\n // 容器可视区域已经填满了,没必要再继续\n if (section.getState().scrollTop > this.getState().containerSize.height) {\n this.pub(RootEvents.InitialRenderCompleted, section)\n return\n }\n\n this.renderInitialLayout(i + 1)\n })\n })\n }\n\n /**\n * 计算滚动阈值对应的 scrollTop 并设置 upperThresholdScrollTop\n * 当距顶部还有 upperThresholdCount 个 FlowItem 时的 scrollTop 值\n */\n private setUpperThresholdScrollTop() {\n // 如果没有设置阈值或阈值为0,则返回0\n if (!this.upperThresholdCount) {\n this.upperThresholdScrollTop = 0\n return 0\n }\n const sectionSize = this.sections.length\n const tracker = Array.from(\n { length: sectionSize },\n () => new Map<number, { accCount: number, accHeight: number }>() // Map<列, { 当前列累计个数,当前列累计高度 }>\n )\n\n // 从第一个分组开始扫描\n loopSeciton: for (let i = 0; i < sectionSize; i++) {\n const section = this.sections[i]\n const sectionTracker = tracker[i]\n const columnMap = section.columnMap\n // 扫描当前分组的每一列\n for (let col = 0; col < columnMap.length; col++) {\n const column = columnMap[col]\n const columnSize = column.length\n if (!sectionTracker.has(col)) {\n if (i === 0) {\n sectionTracker.set(col, { accCount: 0, accHeight: 0 })\n } else {\n const previousSectionTracker = tracker[i - 1]\n sectionTracker.set(col, {\n accCount: Math.max(...[...previousSectionTracker.values()].map((nodeTracker) => nodeTracker.accCount)),\n accHeight: section.getState().scrollTop,\n })\n }\n }\n const colTracker = sectionTracker.get(col)!\n // 扫描当前列的每一行\n loopItem: for (let j = 0; j < columnSize; j++) {\n colTracker.accCount += 1\n colTracker.accHeight += column[j].getState().height + (j === 0 ? 0 : section.rowGap)\n if (colTracker.accCount >= this.upperThresholdCount) {\n break loopItem\n }\n }\n }\n for (const [, colTracker] of sectionTracker) {\n if (colTracker.accCount >= this.upperThresholdCount) {\n this.upperThresholdScrollTop = colTracker.accHeight\n break loopSeciton\n }\n }\n }\n return this.upperThresholdScrollTop\n }\n\n /**\n * 计算滚动阈值对应的 scrollTop 并设置 lowerThresholdScrollTop\n * 当距底部还有 lowerThresholdCount 个 FlowItem 时的 scrollTop 值\n */\n private setLowerThresholdScrollTop() {\n if (this.lowerThresholdCount === 0) {\n this.lowerThresholdScrollTop = this.getState().scrollHeight - this.getState().containerSize.height\n return 0\n }\n const sectionSize = this.sections.length\n const tracker = Array.from(\n { length: sectionSize },\n () => new Map<number, { accCount: number, scrollTop: number }>()\n )\n // 从最后一个分组开始计算\n loopSeciton: for (let i = sectionSize - 1; i >= 0; i--) {\n const section = this.sections[i]\n const sectionTracker = tracker[i]\n const columnMap = section.columnMap\n // 扫描当前分组的每一列\n for (let col = 0; col < columnMap.length; col++) {\n const column = columnMap[col]\n const columnSize = column.length\n if (!sectionTracker.has(col)) {\n if (i === sectionSize - 1) {\n sectionTracker.set(col, { accCount: 0, scrollTop: 0 })\n } else {\n const belowSectionTracker = tracker[i + 1]\n sectionTracker.set(col, {\n accCount: Math.max(...[...belowSectionTracker.values()].map((nodeTracker) => nodeTracker.accCount)),\n scrollTop: 0,\n })\n }\n }\n const colTracker = sectionTracker.get(col)!\n // 从当前列的最后一行开始往前扫描\n loopItem: for (let j = columnSize - 1; j >= 0; j--) {\n colTracker.accCount += 1\n colTracker.scrollTop = column[j].getState().scrollTop\n if (colTracker.accCount >= this.lowerThresholdCount) {\n break loopItem\n }\n }\n }\n\n for (const [, colTracker] of sectionTracker) {\n if (colTracker.accCount >= this.lowerThresholdCount) {\n this.lowerThresholdScrollTop = colTracker.scrollTop\n break loopSeciton\n }\n }\n }\n\n return this.lowerThresholdScrollTop\n }\n\n /**\n * 处理滚动到阈值的情况\n * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件\n */\n private handleReachThreshold() {\n const { upperThresholdScrollTop } = this\n const { scrollOffset, scrollDirection, containerSize } = this.getState()\n if (\n scrollDirection === 'backward' &&\n this.upperThresholdScrollTop !== -Infinity &&\n scrollOffset <= upperThresholdScrollTop\n ) {\n this.pub(RootEvents.ReachUpperThreshold)\n }\n if (\n scrollDirection === 'forward' &&\n this.lowerThresholdCount !== Infinity &&\n scrollOffset + containerSize.height >= this.lowerThresholdScrollTop\n ) {\n this.pub(RootEvents.ReachLowerThreshold)\n }\n }\n\n /**\n * 容器的滚动上边界\n */\n get scrollBoundaryStart() {\n return this.getState().scrollOffset\n }\n\n /**\n * 容器的滚动下边界\n */\n get scrollBoundaryEnd() {\n return this.scrollBoundaryStart + this.getStateIn('containerSize').height\n }\n\n /**\n * 计算每个section的底部位置\n *\n * sectionBottomRange = [ [section1.top, section1.bottom], [section2.top, section2.bottom], ..., [sectionN.top, sectionN.bottom] ]\n *\n * @returns [number,number][]\n */\n get sectionRange() {\n const length = this.sections.length\n if (length === 0) return []\n const range = Array.from({ length }, () => [0, this.sections[0].maxColumnHeight])\n for (let i = 1; i < length; i++) {\n const previous = range[i - 1]\n range[i] = [previous[1], previous[1] + this.sections[i].maxColumnHeight]\n }\n\n return range\n }\n\n /**\n * 计算滚动高度\n */\n public updateScrollHeight() {\n this.setStateIn('scrollHeight', this.sectionRange[this.sectionRange.length - 1][1])\n }\n\n /**\n * 注册分组\n */\n public registerSection(section: Section) {\n const { id, order } = section\n this.sectionMap.set(id, section)\n this.sections[order] = section\n }\n\n /**\n * 注册节点\n */\n public registerNode(node: Node) {\n this.nodeMap.set(node.id, node)\n }\n\n /**\n * 查找分组\n */\n public findSection(id: string) {\n return this.sectionMap.get(id)\n }\n\n /**\n * 查找节点\n */\n public findNode(id: string) {\n return this.nodeMap.get(id)\n }\n\n /**\n * 获取分组渲染区间\n */\n public getSectionRenderRange() {\n const result: [number, number] = [Infinity, -Infinity]\n\n for (let i = 0; i < this.sections.length; i++) {\n const section = this.sections[i]\n if (section.isInRange) {\n result[0] = Math.min(result[0], i)\n result[1] = Math.max(result[1], i)\n }\n }\n\n if (result[0] === Infinity) {\n result[0] = 0\n }\n\n if (result[1] === -Infinity) {\n result[1] = this.sections.length - 1\n }\n\n const scrollDirection = this.getState().scrollDirection\n const [backwardCache, forwardCache] = this.calcCacheSection(result)\n const backwardDistance = scrollDirection === 'backward' ? backwardCache : 0\n const forwardDistance = scrollDirection === 'forward' ? forwardCache : 0\n\n const overscanBackward = result[0] - backwardDistance\n const overscanForward = result[1] + forwardDistance\n\n result[0] = overscanBackward < 0 ? 0 : overscanBackward\n\n result[1] = overscanForward > this.sections.length ? this.sections.length - 1 : overscanForward\n\n return isSameRenderRange(result, this.getState().renderRange) ? this.getState().renderRange : result\n }\n\n /**\n * 计算预渲染的分组个数\n */\n private calcCacheSection(renderRange: [number, number]) {\n const clientHeight = this.getState().containerSize.height\n const sectionCount = this.sectionMap.size\n let [start, end] = renderRange\n let cacheBackward = 1\n let cacheForward = 1\n\n if (start > 0) {\n let acc = this.sections[--start]?.getState().height ?? 0\n while (--start > 0) {\n const prevSection = this.sections[start]\n acc += prevSection.getState().height\n cacheBackward += 1\n if (acc >= clientHeight >>> 1) {\n break\n }\n }\n }\n\n if (end < sectionCount - 1) {\n let acc = this.sections[++end]?.getState().height ?? 0\n while (++end < sectionCount - 1) {\n const nextSection = this.sections[end]\n acc += nextSection.getState().height\n cacheForward += 1\n if (acc >= clientHeight >>> 1) {\n break\n }\n }\n }\n\n return [cacheBackward, cacheForward]\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"root.js","sources":["../../../src/components/water-flow/root.ts"],"sourcesContent":["/* eslint-disable no-labels */\nimport { cancelAnimationFrame, requestAnimationFrame } from '@tarojs/runtime'\nimport { nextTick } from '@tarojs/taro'\n\nimport { getRectSizeSync } from '../../utils'\nimport { Node } from './node'\nimport { Section } from './section'\nimport { StatefulEventBus } from './stateful-event-bus'\nimport { getSysInfo, isSameRenderRange } from './utils'\n\nimport type { BaseProps, ScrollDirection, Size, WaterFlowProps } from './interface'\n\nexport type RootProps = Pick<WaterFlowProps, 'cacheCount' | 'lowerThresholdCount' | 'upperThresholdCount'> &\nRequired<Pick<BaseProps, 'id'>> & {\n /** scrollElement 模式下为 true,不测量自有容器;此时需布局全部 section 以展开完整高度 */\n skipContainerMeasure?: boolean\n}\n\nconst { windowHeight, windowWidth } = getSysInfo()\n\ntype RootState = {\n /** 是否在滚动中 */\n isScrolling: boolean\n /** 滚动偏移量 */\n scrollOffset: number\n /**\n * 滚动方向\n *\n * - forward 向下滚动\n *\n * - backward 向上滚动\n */\n scrollDirection: ScrollDirection\n /** 滚动高度 */\n scrollHeight: number\n /** 容器的尺寸信息 */\n containerSize: Size\n /** 渲染的分组区间范围 */\n renderRange: [number, number]\n}\n\nexport const RootEvents = {\n ReachUpperThreshold: Symbol.for('ReachUpperThreshold'),\n ReachLowerThreshold: Symbol.for('ReachLowerThreshold'),\n Resize: Symbol.for('Resize'),\n AllSectionsLayouted: Symbol.for('AllSectionsLayouted'),\n InitialRenderCompleted: Symbol.for('InitialRenderCompleted'),\n}\n\ntype Events = keyof typeof RootEvents\n\n/**\n * 数据模型继承自有状态的事件总线,便于在节点之间通信,以及通过 useSyncExternalStore 关联 React 视图\n */\nexport class Root extends StatefulEventBus<RootState, Events> {\n /**\n * 瀑布流根节点唯一标识\n */\n id: string\n /**\n * 分组映射表,便于查找分组\n */\n sectionMap: Map<string, Section> = new Map()\n /**\n * 节点映射表,便于查找节点\n */\n nodeMap: Map<string, Node> = new Map()\n /**\n * 分组列表,基于计算出的渲染的分组区间范围 sections.slice(start, end + 1) 进行渲染\n */\n sections: Section[] = []\n /**\n * 设置预加载的 Item 条数。\n */\n cacheCount = 1\n\n upperThresholdCount = 0\n\n lowerThresholdCount = 0\n\n /**\n * 触发滚动阈值对应的 scrollTop 值\n */\n upperThresholdScrollTop = -Infinity\n\n /**\n * 触发滚动阈值对应的 scrollTop 值\n */\n lowerThresholdScrollTop = Infinity\n\n /** scrollElement 模式下为 true,需布局全部 section 以展开完整高度供父容器滚动 */\n skipContainerMeasure = false\n\n /** 当前是否处于触顶区域;初始为 true(起始在顶部),只有从 false→true 时才触发事件 */\n private _inUpperZone = true\n /** 当前是否处于触底区域;初始为 false */\n private _inLowerZone = false\n /** scrollHeight 防抖(raf),避免 pushNodes + 测量 导致的 先涨后跌 闪动 */\n private _scrollHeightRafId: number | null = null\n\n constructor(props: RootProps) {\n const { id, cacheCount, lowerThresholdCount, upperThresholdCount, skipContainerMeasure } = props\n super({\n isScrolling: false,\n scrollOffset: 0,\n scrollDirection: 'forward',\n scrollHeight: windowHeight,\n renderRange: [0, 0],\n containerSize: {\n width: windowWidth,\n height: windowHeight,\n },\n })\n Object.assign(this, {\n id,\n cacheCount,\n lowerThresholdCount,\n upperThresholdCount,\n skipContainerMeasure: !!skipContainerMeasure,\n })\n this.setupSubscriptions()\n if (!skipContainerMeasure) {\n getRectSizeSync(`#${id}`, 100).then(({ width = windowWidth, height = windowHeight }) => {\n this.setStateIn('containerSize', {\n width,\n height,\n })\n })\n }\n this.renderInitialLayout()\n }\n\n /**\n * 设置订阅事件\n */\n private setupSubscriptions() {\n /**\n * 滚动过程中计算渲染的分组区间\n * 滚动过程中分组的最大高度会发生更新,可以在这时计算滚动高度\n */\n this.sub('scrollOffset', () => {\n this.setStateIn('renderRange', this.getSectionRenderRange())\n this.handleReachThreshold()\n this.updateScrollHeight()\n })\n\n this.sub('scrollOffset', () => {\n const sectionSize = this.sections.length\n const lastSection = this.sections[sectionSize - 1]\n // 最后一个分组的每一列最后一行都已经完成了布局计算,那么这个时候的总高度应该是准确的\n if (lastSection?.columnMap.every((column) => column[column.length - 1]?.getState().layouted)) {\n this.setLowerThresholdScrollTop()\n }\n })\n\n this.sub(RootEvents.AllSectionsLayouted, () => {\n this.updateScrollHeight()\n this.setUpperThresholdScrollTop()\n this.setLowerThresholdScrollTop()\n })\n\n this.sub(RootEvents.Resize, () => {\n this.updateScrollHeight()\n this.setUpperThresholdScrollTop()\n this.setLowerThresholdScrollTop()\n })\n }\n\n /**\n * 渐进式渲染\n *\n * 因为初始没法知道每个分组的高度信息,不知道渲染边界,所以需要渐进式渲染\n *\n * 当目前的渲染批次的首个分组的scrollTop大于容器的高度,说明容器可视区域已经填满,没必要再往下渲染了\n *\n * @param [i=0] 从第几个分组开始渲染\n *\n */\n renderInitialLayout(i = 0) {\n nextTick(() => {\n const sectionSize = this.sections.length\n\n if (i >= sectionSize || i < 0) {\n this.pub(RootEvents.InitialRenderCompleted, null)\n return\n }\n const section = this.sections[i]\n section.layoutedSignal.promise.then(() => {\n this.setStateIn('renderRange', [0, i + 1 > sectionSize ? sectionSize - 1 : i + 1])\n // skipContainerMeasure(nestedScroll 模式):需布局全部 section,使 scrollHeight 展开供父容器滚动\n // default 模式:容器可视区域已填满则提前终止,减少首屏渲染\n if (\n !this.skipContainerMeasure &&\n section.getState().scrollTop > this.getState().containerSize.height\n ) {\n this.pub(RootEvents.InitialRenderCompleted, section)\n return\n }\n\n this.renderInitialLayout(i + 1)\n })\n })\n }\n\n /**\n * 计算滚动阈值对应的 scrollTop 并设置 upperThresholdScrollTop\n * 当距顶部还有 upperThresholdCount 个 FlowItem 时的 scrollTop 值\n */\n private setUpperThresholdScrollTop() {\n // 如果没有设置阈值或阈值为0,则返回0\n if (!this.upperThresholdCount) {\n this.upperThresholdScrollTop = 0\n return 0\n }\n const sectionSize = this.sections.length\n const tracker = Array.from(\n { length: sectionSize },\n () => new Map<number, { accCount: number, accHeight: number }>() // Map<列, { 当前列累计个数,当前列累计高度 }>\n )\n\n // 从第一个分组开始扫描\n loopSeciton: for (let i = 0; i < sectionSize; i++) {\n const section = this.sections[i]\n const sectionTracker = tracker[i]\n const columnMap = section.columnMap\n // 扫描当前分组的每一列\n for (let col = 0; col < columnMap.length; col++) {\n const column = columnMap[col]\n const columnSize = column.length\n if (!sectionTracker.has(col)) {\n if (i === 0) {\n sectionTracker.set(col, { accCount: 0, accHeight: 0 })\n } else {\n const previousSectionTracker = tracker[i - 1]\n sectionTracker.set(col, {\n accCount: Math.max(...[...previousSectionTracker.values()].map((nodeTracker) => nodeTracker.accCount)),\n accHeight: section.getState().scrollTop,\n })\n }\n }\n const colTracker = sectionTracker.get(col)!\n // 扫描当前列的每一行\n loopItem: for (let j = 0; j < columnSize; j++) {\n colTracker.accCount += 1\n colTracker.accHeight += column[j].getState().height + (j === 0 ? 0 : section.rowGap)\n if (colTracker.accCount >= this.upperThresholdCount) {\n break loopItem\n }\n }\n }\n for (const [, colTracker] of sectionTracker) {\n if (colTracker.accCount >= this.upperThresholdCount) {\n this.upperThresholdScrollTop = colTracker.accHeight\n break loopSeciton\n }\n }\n }\n return this.upperThresholdScrollTop\n }\n\n /**\n * 计算滚动阈值对应的 scrollTop 并设置 lowerThresholdScrollTop\n * 当距底部还有 lowerThresholdCount 个 FlowItem 时的 scrollTop 值\n */\n private setLowerThresholdScrollTop() {\n // 与 setUpperThresholdScrollTop 一致:0 或 undefined 时用「内容底 - 容器高」作为触底阈值\n if (!this.lowerThresholdCount) {\n // 必须用 sectionRange 实时计算,避免依赖可能未更新的 scrollHeight 状态\n const range = this.sectionRange\n const totalHeight = range.length > 0 ? range[range.length - 1][1] : 0\n this.lowerThresholdScrollTop = totalHeight - this.getState().containerSize.height\n return 0\n }\n const sectionSize = this.sections.length\n const tracker = Array.from(\n { length: sectionSize },\n () => new Map<number, { accCount: number, scrollTop: number }>()\n )\n // 从最后一个分组开始计算\n loopSeciton: for (let i = sectionSize - 1; i >= 0; i--) {\n const section = this.sections[i]\n const sectionTracker = tracker[i]\n const columnMap = section.columnMap\n // 扫描当前分组的每一列\n for (let col = 0; col < columnMap.length; col++) {\n const column = columnMap[col]\n const columnSize = column.length\n if (!sectionTracker.has(col)) {\n if (i === sectionSize - 1) {\n sectionTracker.set(col, { accCount: 0, scrollTop: 0 })\n } else {\n const belowSectionTracker = tracker[i + 1]\n sectionTracker.set(col, {\n accCount: Math.max(...[...belowSectionTracker.values()].map((nodeTracker) => nodeTracker.accCount)),\n scrollTop: 0,\n })\n }\n }\n const colTracker = sectionTracker.get(col)!\n // 从当前列的最后一行开始往前扫描\n loopItem: for (let j = columnSize - 1; j >= 0; j--) {\n colTracker.accCount += 1\n colTracker.scrollTop = column[j].getState().scrollTop\n if (colTracker.accCount >= this.lowerThresholdCount) {\n break loopItem\n }\n }\n }\n\n for (const [, colTracker] of sectionTracker) {\n if (colTracker.accCount >= this.lowerThresholdCount) {\n this.lowerThresholdScrollTop = colTracker.scrollTop\n break loopSeciton\n }\n }\n }\n\n return this.lowerThresholdScrollTop\n }\n\n /**\n * 处理滚动到阈值的情况\n * 检测当前滚动位置是否达到了上下阈值,并触发相应的事件\n * scrollElement 模式:scrollOffset 为内容内偏移(scrollTop - startOffset),upper/lowerThresholdScrollTop 基于本组件内容计算,触顶/触底以本 WaterFlow 内容为基准\n */\n private handleReachThreshold() {\n const { scrollOffset, containerSize } = this.getState()\n const inUpper = this.upperThresholdScrollTop !== -Infinity && scrollOffset <= this.upperThresholdScrollTop\n const inLower = this.lowerThresholdScrollTop !== Infinity && scrollOffset + containerSize.height >= this.lowerThresholdScrollTop\n if (inUpper && !this._inUpperZone) this.pub(RootEvents.ReachUpperThreshold)\n if (inLower && !this._inLowerZone) this.pub(RootEvents.ReachLowerThreshold)\n this._inUpperZone = inUpper\n this._inLowerZone = inLower\n }\n\n /**\n * 容器的滚动上边界\n */\n get scrollBoundaryStart() {\n return this.getState().scrollOffset\n }\n\n /**\n * 容器的滚动下边界\n */\n get scrollBoundaryEnd() {\n return this.scrollBoundaryStart + this.getStateIn('containerSize').height\n }\n\n /**\n * 计算每个section的底部位置\n *\n * sectionBottomRange = [ [section1.top, section1.bottom], [section2.top, section2.bottom], ..., [sectionN.top, sectionN.bottom] ]\n *\n * @returns [number,number][]\n */\n get sectionRange() {\n const length = this.sections.length\n if (length === 0) return []\n const range = Array.from({ length }, () => [0, this.sections[0].maxColumnHeight])\n for (let i = 1; i < length; i++) {\n const previous = range[i - 1]\n const prevSection = this.sections[i - 1]\n const gap = prevSection.rowGap ?? 0\n range[i] = [previous[1] + gap, previous[1] + gap + this.sections[i].maxColumnHeight]\n }\n\n return range\n }\n\n /**\n * 计算滚动高度\n * 防抖一帧(raf),避免 pushNodes 后测量完成前出现 先涨(未测量默认高度)后跌(真实高度)导致的闪动\n * @param immediate 为 true 时立即执行,不防抖(pushNodes 调用,避免容器高度滞后导致往上抖动)\n */\n public updateScrollHeight(immediate = false) {\n const flush = () => {\n const next = this.sectionRange[this.sectionRange.length - 1]?.[1] ?? 0\n this.setStateIn('scrollHeight', next)\n }\n if (immediate) {\n if (this._scrollHeightRafId != null) {\n cancelAnimationFrame(this._scrollHeightRafId)\n this._scrollHeightRafId = null\n }\n flush()\n return\n }\n if (this._scrollHeightRafId != null) {\n cancelAnimationFrame(this._scrollHeightRafId)\n }\n this._scrollHeightRafId = requestAnimationFrame(() => {\n this._scrollHeightRafId = null\n flush()\n })\n }\n\n /**\n * 注册分组\n */\n public registerSection(section: Section) {\n const { id, order } = section\n this.sectionMap.set(id, section)\n this.sections[order] = section\n }\n\n /**\n * 注册节点\n */\n public registerNode(node: Node) {\n this.nodeMap.set(node.id, node)\n }\n\n /**\n * 查找分组\n */\n public findSection(id: string) {\n return this.sectionMap.get(id)\n }\n\n /**\n * 查找节点\n */\n public findNode(id: string) {\n return this.nodeMap.get(id)\n }\n\n /**\n * 获取分组渲染区间\n */\n public getSectionRenderRange() {\n const result: [number, number] = [Infinity, -Infinity]\n\n for (let i = 0; i < this.sections.length; i++) {\n const section = this.sections[i]\n if (section.isInRange) {\n result[0] = Math.min(result[0], i)\n result[1] = Math.max(result[1], i)\n }\n }\n\n if (result[0] === Infinity) {\n result[0] = 0\n }\n\n if (result[1] === -Infinity) {\n result[1] = this.sections.length - 1\n }\n\n const scrollDirection = this.getState().scrollDirection\n const [backwardCache, forwardCache] = this.calcCacheSection(result)\n const backwardDistance = scrollDirection === 'backward' ? backwardCache : 0\n const forwardDistance = scrollDirection === 'forward' ? forwardCache : 0\n\n const overscanBackward = result[0] - backwardDistance\n const overscanForward = result[1] + forwardDistance\n\n result[0] = overscanBackward < 0 ? 0 : overscanBackward\n\n result[1] = overscanForward > this.sections.length ? this.sections.length - 1 : overscanForward\n\n const prevRange = this.getState().renderRange\n return isSameRenderRange(result, prevRange) ? prevRange : result\n }\n\n /**\n * 计算预渲染的分组个数\n */\n private calcCacheSection(renderRange: [number, number]) {\n const clientHeight = this.getState().containerSize.height\n const sectionCount = this.sectionMap.size\n let [start, end] = renderRange\n let cacheBackward = 1\n let cacheForward = 1\n\n if (start > 0) {\n let acc = this.sections[--start]?.getState().height ?? 0\n while (--start > 0) {\n const prevSection = this.sections[start]\n acc += prevSection.getState().height\n cacheBackward += 1\n if (acc >= clientHeight >>> 1) {\n break\n }\n }\n }\n\n if (end < sectionCount - 1) {\n let acc = this.sections[++end]?.getState().height ?? 0\n while (++end < sectionCount - 1) {\n const nextSection = this.sections[end]\n acc += nextSection.getState().height\n cacheForward += 1\n if (acc >= clientHeight >>> 1) {\n break\n }\n }\n }\n\n return [cacheBackward, cacheForward]\n }\n}\n"],"names":[],"mappings":"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"}
@@ -99,7 +99,7 @@ export declare class Section extends StatefulEventBus<SectionState> {
99
99
  */
100
100
  private updateNodes;
101
101
  /**
102
- * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度之和
102
+ * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度 + rowGap 之和
103
103
  */
104
104
  private calcScrollTop;
105
105
  /**
@@ -127,7 +127,10 @@ class Section extends StatefulEventBus {
127
127
  for (; start < this.root.sections.length; start++) {
128
128
  const currentSection = this.root.sections[start - 1];
129
129
  const nextSection = this.root.sections[start];
130
- nextSection.setStateIn('scrollTop', currentSection.getState().scrollTop + currentSection.getState().height + this.rowGap);
130
+ // 使用 maxColumnHeight 替代 getState().height,避免 pushNodes 后 state 未同步导致 footer 错位
131
+ const effectiveHeight = currentSection.maxColumnHeight;
132
+ const newScrollTop = currentSection.getState().scrollTop + effectiveHeight + this.rowGap;
133
+ nextSection.setStateIn('scrollTop', newScrollTop);
131
134
  nextSection.updateNodes();
132
135
  }
133
136
  }
@@ -165,10 +168,10 @@ class Section extends StatefulEventBus {
165
168
  }
166
169
  }
167
170
  /**
168
- * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度之和
171
+ * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度 + rowGap 之和
169
172
  */
170
173
  calcScrollTop() {
171
- return this.root.sections.slice(0, this.order).reduce((acc, section) => acc + section.maxColumnHeight, 0);
174
+ return this.root.sections.slice(0, this.order).reduce((acc, section) => { var _a; return acc + section.maxColumnHeight + ((_a = section.rowGap) !== null && _a !== void 0 ? _a : 0); }, 0);
172
175
  }
173
176
  /**
174
177
  * 计算当前分组内每列应该渲染的节点索引区间
@@ -204,7 +207,8 @@ class Section extends StatefulEventBus {
204
207
  result[i][0] = overscanBackward < 0 ? 0 : overscanBackward;
205
208
  result[i][1] = overscanForward > column.length ? column.length - 1 : overscanForward;
206
209
  }
207
- return isSameRenderRange(result, this.getState().renderRange) ? this.getState().renderRange : result;
210
+ const prevRange = this.getState().renderRange;
211
+ return isSameRenderRange(result, prevRange) ? prevRange : result;
208
212
  }
209
213
  pushNode(nodeIndex, col) {
210
214
  const { row: rowIndex, col: columnIndex } = getMatrixPosition(nodeIndex, col);
@@ -224,8 +228,12 @@ class Section extends StatefulEventBus {
224
228
  }
225
229
  this.count += count;
226
230
  this.root.lowerThresholdScrollTop = Infinity;
231
+ // 同步 section state.height,避免与 maxColumnHeight 不一致导致 footer 错位
232
+ this.setStateIn('height', this.maxColumnHeight);
227
233
  this.updateNodes();
228
234
  this.updateBehindSectionsPosition();
235
+ // 立即更新 scrollHeight,避免防抖导致容器高度滞后引发往上抖动
236
+ this.root.updateScrollHeight(true);
229
237
  }
230
238
  }
231
239
 
@@ -1 +1 @@
1
- {"version":3,"file":"section.js","sources":["../../../src/components/water-flow/section.ts"],"sourcesContent":["import { debounce } from '../../utils'\nimport { Size } from './interface'\nimport { Node } from './node'\nimport { Root, RootEvents } from './root'\nimport { StatefulEventBus } from './stateful-event-bus'\nimport { createImperativePromise, getMatrixPosition, isSameRenderRange } from './utils'\n\nexport interface SectionProps {\n /** 分组的唯一标识 */\n id: string\n /** 分组的列数 */\n col: number\n /** 分组的顺序 */\n order: number\n /** 节点数量 */\n count: number\n /** 该分组的行间距 */\n rowGap: number\n /** 该分组的列间距 */\n columnGap: number\n}\n\n/**\n * 分组状态\n */\ntype SectionState = {\n /**\n * 分组是否已经布局计算\n */\n layouted: boolean\n /**\n * 分组顶部距离容器顶部的距离\n */\n scrollTop: number\n /**\n * 分组的高度\n */\n height: number\n /**\n * 每个列的渲染范围\n * 每个元素为一个二元组,第一个元素为起始索引,第二个元素为结束索引\n */\n renderRange: [number, number][]\n}\n\nexport const SectionEvents = {\n AllNodesLayouted: Symbol.for('AllNodesLayouted'),\n Resize: Symbol.for('Resize'),\n}\n\nexport class Section extends StatefulEventBus<SectionState> {\n id: string\n order: number\n col: number\n columnMap: Node[][]\n nodes: Map<string, Node> = new Map()\n defaultSize = 200\n count = 0\n rowGap = 0\n columnGap = 0\n layoutedSignal = createImperativePromise()\n\n constructor(public root: Root, props: SectionProps) {\n const { id, col, order, count, rowGap, columnGap } = props\n super({\n layouted: false,\n scrollTop: 0,\n height: 0,\n renderRange: Array.from({ length: col }, () => [0, 0]),\n })\n Object.assign(this, {\n id,\n col,\n count,\n order,\n rowGap,\n columnGap,\n columnMap: Array.from({ length: col }, () => []),\n })\n this.initializeColumnMap()\n root.registerSection(this)\n this.setupSubscriptions()\n }\n\n /**\n * 订阅事件\n */\n private setupSubscriptions() {\n // 分组的所有节点完成初次布局计算,Nodes的实际高度已经拿到,那么这时分组的高度是确定的,距离滚动容器的顶部距离也是确定的,可以开始计算\n this.sub(SectionEvents.AllNodesLayouted, () => {\n this.setStateBatch({\n scrollTop: this.calcScrollTop(),\n height: this.maxColumnHeight,\n })\n this.updateNodes()\n this.setStateIn('renderRange', this.getNodeRenderRange())\n this.setStateIn('layouted', true)\n this.layoutedSignal.resolve()\n if (this.root.sections.every((section) => section.getState().layouted)) {\n this.root.pub(RootEvents.AllSectionsLayouted)\n }\n })\n // 滚动过程中,如果分组自身可见,那么需要计算分组内应该渲染的元素节点索引区间\n this.root.sub('scrollOffset', () => {\n if (this.isInRange) {\n this.setStateIn('renderRange', this.getNodeRenderRange())\n }\n })\n\n /**\n * 对应分组内的节点尺寸发生变化,需要重新进行相关计算\n * 1. 重新计算尺寸发生变化的节点所在列的所有节点位置信息\n * 2. 重新计算分组的高度\n * 3. 重新计算当前分组之后的所有分组的scrollTop以及分组内的节点位置\n * 4. 更新分组内节点的渲染范围\n */\n this.sub<{ node: Node, newSize: Size, originalSize: Size }>(\n SectionEvents.Resize,\n debounce(() => {\n this.setStateIn('height', this.maxColumnHeight)\n this.updateBehindSectionsPosition()\n if (this.isInRange) {\n this.setStateIn('renderRange', this.getNodeRenderRange())\n }\n this.root.pub(RootEvents.Resize)\n })\n )\n }\n\n /**\n * 获取当前分组的最大高度,分组的最大高度由分组最高列决定\n * @returns 当前分组的最大高度\n */\n get maxColumnHeight() {\n return Math.max(\n ...this.columnMap.map(\n (column) => column.reduce((buf, node) => buf + node.getState().height, 0) + (column.length - 1) * this.rowGap\n )\n )\n }\n\n /**\n * 当前分组是否在可视区域\n *\n * 滚动偏移为 scrollOffset,容器的高度为 containerSize.height\n *\n * 当前容器滚动上边界(scrollBoundaryStart)为 scrollOffset,容器滚动的下边界(scrollBoundaryEnd)为 scrollOffset + containerSize.height\n *\n * 如果分组的 scrollTop 小于滚动下边界并且 scrollTop + 分组高度大于滚动上边界,那么分组在可视区域\n */\n get isInRange() {\n const { scrollBoundaryStart, scrollBoundaryEnd } = this.root\n const { height: sectionHeight, scrollTop: sectionScrollTop } = this.getState()\n return sectionScrollTop <= scrollBoundaryEnd && sectionScrollTop + sectionHeight >= scrollBoundaryStart\n }\n\n /**\n * 注册节点\n */\n private register(node: Node) {\n const { col, order } = node\n this.columnMap[col][order] = node\n this.nodes.set(node.id, node)\n }\n\n /**\n * 初始化分组内的列,即将一维数组转二维数组\n */\n private initializeColumnMap() {\n const { count, col } = this\n for (let i = 0; i < count; i++) {\n this.pushNode(i, col)\n }\n }\n\n /**\n * 更新当前分组之后的分组的位置信息\n */\n private updateBehindSectionsPosition() {\n let start = this.order + 1\n if (start > this.root.sections.length) {\n return\n }\n for (; start < this.root.sections.length; start++) {\n const currentSection = this.root.sections[start - 1]\n const nextSection = this.root.sections[start]\n nextSection.setStateIn(\n 'scrollTop',\n currentSection.getState().scrollTop + currentSection.getState().height + this.rowGap\n )\n nextSection.updateNodes()\n }\n }\n\n /**\n * 更新指定列的节点位置信息\n * @param col 列索引\n */\n private updateColumnNode(col: number) {\n const column = this.columnMap[col]\n const { scrollTop: sectionScrollTop } = this.getState()\n for (let i = 0; i < column.length; i++) {\n const node = column[i]\n if (i === 0) {\n node.setStateBatch({\n scrollTop: sectionScrollTop,\n top: 0,\n })\n } else {\n const prevNode = column[i - 1]\n const { scrollTop: prevNodeScrollTop, height: prevNodeHeight, top: prevNodeTop } = prevNode.getState()\n node.setStateBatch({\n scrollTop: prevNodeScrollTop + prevNodeHeight + this.rowGap,\n top: prevNodeHeight + prevNodeTop + this.rowGap,\n })\n }\n }\n }\n\n /**\n * 更新每列节点的位置\n */\n private updateNodes() {\n for (let col = 0; col < this.columnMap.length; col++) {\n this.updateColumnNode(col)\n }\n }\n\n /**\n * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度之和\n */\n private calcScrollTop() {\n return this.root.sections.slice(0, this.order).reduce((acc, section) => acc + section.maxColumnHeight, 0)\n }\n\n /**\n * 计算当前分组内每列应该渲染的节点索引区间\n */\n public getNodeRenderRange() {\n if (!this.isInRange) {\n return Array.from({ length: this.col }, () => [0, -1] as [number, number])\n }\n\n const result = Array.from({ length: this.col }, () => [Infinity, -Infinity] as unknown as [number, number])\n for (let i = 0; i < this.columnMap.length; i++) {\n const column = this.columnMap[i]\n for (let j = 0; j < column.length; j++) {\n const node = column[j]\n if (node.isInRange) {\n result[i][0] = Math.min(result[i][0], j)\n result[i][1] = Math.max(result[i][1], j)\n }\n }\n const start = result[i][0]\n const end = result[i][1]\n if (start === Infinity) {\n result[i][0] = 0\n }\n if (end === -Infinity) {\n result[i][1] = -1\n }\n\n const cacheCount = this.root.cacheCount\n const scrollDirection = this.root.getState().scrollDirection\n const backwardDistance = scrollDirection === 'backward' ? cacheCount : 0\n const forwardDistance = scrollDirection === 'forward' ? cacheCount : 0\n const overscanBackward = result[i][0] - backwardDistance\n const overscanForward = result[i][1] + forwardDistance\n result[i][0] = overscanBackward < 0 ? 0 : overscanBackward\n result[i][1] = overscanForward > column.length ? column.length - 1 : overscanForward\n }\n\n return isSameRenderRange(result, this.getState().renderRange) ? this.getState().renderRange : result\n }\n\n public pushNode(nodeIndex: number, col: number) {\n const { row: rowIndex, col: columnIndex } = getMatrixPosition(nodeIndex, col)\n const node = new Node(this.root, this, {\n childIndex: nodeIndex,\n order: rowIndex,\n col: columnIndex,\n height: this.defaultSize,\n })\n this.register(node)\n this.root.registerNode(node)\n }\n\n public pushNodes(count: number) {\n const { count: originalCount, col } = this\n for (let i = originalCount; i < originalCount + count; i++) {\n this.pushNode(i, col)\n }\n this.count += count\n this.root.lowerThresholdScrollTop = Infinity\n this.updateNodes()\n this.updateBehindSectionsPosition()\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"section.js","sources":["../../../src/components/water-flow/section.ts"],"sourcesContent":["import { debounce } from '../../utils'\nimport { Size } from './interface'\nimport { Node } from './node'\nimport { Root, RootEvents } from './root'\nimport { StatefulEventBus } from './stateful-event-bus'\nimport { createImperativePromise, getMatrixPosition, isSameRenderRange } from './utils'\n\nexport interface SectionProps {\n /** 分组的唯一标识 */\n id: string\n /** 分组的列数 */\n col: number\n /** 分组的顺序 */\n order: number\n /** 节点数量 */\n count: number\n /** 该分组的行间距 */\n rowGap: number\n /** 该分组的列间距 */\n columnGap: number\n}\n\n/**\n * 分组状态\n */\ntype SectionState = {\n /**\n * 分组是否已经布局计算\n */\n layouted: boolean\n /**\n * 分组顶部距离容器顶部的距离\n */\n scrollTop: number\n /**\n * 分组的高度\n */\n height: number\n /**\n * 每个列的渲染范围\n * 每个元素为一个二元组,第一个元素为起始索引,第二个元素为结束索引\n */\n renderRange: [number, number][]\n}\n\nexport const SectionEvents = {\n AllNodesLayouted: Symbol.for('AllNodesLayouted'),\n Resize: Symbol.for('Resize'),\n}\n\nexport class Section extends StatefulEventBus<SectionState> {\n id: string\n order: number\n col: number\n columnMap: Node[][]\n nodes: Map<string, Node> = new Map()\n defaultSize = 200\n count = 0\n rowGap = 0\n columnGap = 0\n layoutedSignal = createImperativePromise()\n\n constructor(public root: Root, props: SectionProps) {\n const { id, col, order, count, rowGap, columnGap } = props\n super({\n layouted: false,\n scrollTop: 0,\n height: 0,\n renderRange: Array.from({ length: col }, () => [0, 0]),\n })\n Object.assign(this, {\n id,\n col,\n count,\n order,\n rowGap,\n columnGap,\n columnMap: Array.from({ length: col }, () => []),\n })\n this.initializeColumnMap()\n root.registerSection(this)\n this.setupSubscriptions()\n }\n\n /**\n * 订阅事件\n */\n private setupSubscriptions() {\n // 分组的所有节点完成初次布局计算,Nodes的实际高度已经拿到,那么这时分组的高度是确定的,距离滚动容器的顶部距离也是确定的,可以开始计算\n this.sub(SectionEvents.AllNodesLayouted, () => {\n this.setStateBatch({\n scrollTop: this.calcScrollTop(),\n height: this.maxColumnHeight,\n })\n this.updateNodes()\n this.setStateIn('renderRange', this.getNodeRenderRange())\n this.setStateIn('layouted', true)\n this.layoutedSignal.resolve()\n if (this.root.sections.every((section) => section.getState().layouted)) {\n this.root.pub(RootEvents.AllSectionsLayouted)\n }\n })\n // 滚动过程中,如果分组自身可见,那么需要计算分组内应该渲染的元素节点索引区间\n this.root.sub('scrollOffset', () => {\n if (this.isInRange) {\n this.setStateIn('renderRange', this.getNodeRenderRange())\n }\n })\n\n /**\n * 对应分组内的节点尺寸发生变化,需要重新进行相关计算\n * 1. 重新计算尺寸发生变化的节点所在列的所有节点位置信息\n * 2. 重新计算分组的高度\n * 3. 重新计算当前分组之后的所有分组的scrollTop以及分组内的节点位置\n * 4. 更新分组内节点的渲染范围\n */\n this.sub<{ node: Node, newSize: Size, originalSize: Size }>(\n SectionEvents.Resize,\n debounce(() => {\n this.setStateIn('height', this.maxColumnHeight)\n this.updateBehindSectionsPosition()\n if (this.isInRange) {\n this.setStateIn('renderRange', this.getNodeRenderRange())\n }\n this.root.pub(RootEvents.Resize)\n })\n )\n }\n\n /**\n * 获取当前分组的最大高度,分组的最大高度由分组最高列决定\n * @returns 当前分组的最大高度\n */\n get maxColumnHeight() {\n return Math.max(\n ...this.columnMap.map(\n (column) => column.reduce((buf, node) => buf + node.getState().height, 0) + (column.length - 1) * this.rowGap\n )\n )\n }\n\n /**\n * 当前分组是否在可视区域\n *\n * 滚动偏移为 scrollOffset,容器的高度为 containerSize.height\n *\n * 当前容器滚动上边界(scrollBoundaryStart)为 scrollOffset,容器滚动的下边界(scrollBoundaryEnd)为 scrollOffset + containerSize.height\n *\n * 如果分组的 scrollTop 小于滚动下边界并且 scrollTop + 分组高度大于滚动上边界,那么分组在可视区域\n */\n get isInRange() {\n const { scrollBoundaryStart, scrollBoundaryEnd } = this.root\n const { height: sectionHeight, scrollTop: sectionScrollTop } = this.getState()\n return sectionScrollTop <= scrollBoundaryEnd && sectionScrollTop + sectionHeight >= scrollBoundaryStart\n }\n\n /**\n * 注册节点\n */\n private register(node: Node) {\n const { col, order } = node\n this.columnMap[col][order] = node\n this.nodes.set(node.id, node)\n }\n\n /**\n * 初始化分组内的列,即将一维数组转二维数组\n */\n private initializeColumnMap() {\n const { count, col } = this\n for (let i = 0; i < count; i++) {\n this.pushNode(i, col)\n }\n }\n\n /**\n * 更新当前分组之后的分组的位置信息\n */\n private updateBehindSectionsPosition() {\n let start = this.order + 1\n if (start > this.root.sections.length) {\n return\n }\n for (; start < this.root.sections.length; start++) {\n const currentSection = this.root.sections[start - 1]\n const nextSection = this.root.sections[start]\n // 使用 maxColumnHeight 替代 getState().height,避免 pushNodes 后 state 未同步导致 footer 错位\n const effectiveHeight = currentSection.maxColumnHeight\n const newScrollTop = currentSection.getState().scrollTop + effectiveHeight + this.rowGap\n nextSection.setStateIn('scrollTop', newScrollTop)\n nextSection.updateNodes()\n }\n }\n\n /**\n * 更新指定列的节点位置信息\n * @param col 列索引\n */\n private updateColumnNode(col: number) {\n const column = this.columnMap[col]\n const { scrollTop: sectionScrollTop } = this.getState()\n for (let i = 0; i < column.length; i++) {\n const node = column[i]\n if (i === 0) {\n node.setStateBatch({\n scrollTop: sectionScrollTop,\n top: 0,\n })\n } else {\n const prevNode = column[i - 1]\n const { scrollTop: prevNodeScrollTop, height: prevNodeHeight, top: prevNodeTop } = prevNode.getState()\n node.setStateBatch({\n scrollTop: prevNodeScrollTop + prevNodeHeight + this.rowGap,\n top: prevNodeHeight + prevNodeTop + this.rowGap,\n })\n }\n }\n }\n\n /**\n * 更新每列节点的位置\n */\n private updateNodes() {\n for (let col = 0; col < this.columnMap.length; col++) {\n this.updateColumnNode(col)\n }\n }\n\n /**\n * 计算当前分组的 scrollTop,即该分组之前的所有分组的最大列高度 + rowGap 之和\n */\n private calcScrollTop() {\n return this.root.sections.slice(0, this.order).reduce(\n (acc, section) => acc + section.maxColumnHeight + (section.rowGap ?? 0),\n 0\n )\n }\n\n /**\n * 计算当前分组内每列应该渲染的节点索引区间\n */\n public getNodeRenderRange() {\n if (!this.isInRange) {\n return Array.from({ length: this.col }, () => [0, -1] as [number, number])\n }\n\n const result = Array.from({ length: this.col }, () => [Infinity, -Infinity] as unknown as [number, number])\n for (let i = 0; i < this.columnMap.length; i++) {\n const column = this.columnMap[i]\n for (let j = 0; j < column.length; j++) {\n const node = column[j]\n if (node.isInRange) {\n result[i][0] = Math.min(result[i][0], j)\n result[i][1] = Math.max(result[i][1], j)\n }\n }\n const start = result[i][0]\n const end = result[i][1]\n if (start === Infinity) {\n result[i][0] = 0\n }\n if (end === -Infinity) {\n result[i][1] = -1\n }\n\n const cacheCount = this.root.cacheCount\n const scrollDirection = this.root.getState().scrollDirection\n const backwardDistance = scrollDirection === 'backward' ? cacheCount : 0\n const forwardDistance = scrollDirection === 'forward' ? cacheCount : 0\n const overscanBackward = result[i][0] - backwardDistance\n const overscanForward = result[i][1] + forwardDistance\n result[i][0] = overscanBackward < 0 ? 0 : overscanBackward\n result[i][1] = overscanForward > column.length ? column.length - 1 : overscanForward\n }\n\n const prevRange = this.getState().renderRange\n return isSameRenderRange(result, prevRange) ? prevRange : result\n }\n\n public pushNode(nodeIndex: number, col: number) {\n const { row: rowIndex, col: columnIndex } = getMatrixPosition(nodeIndex, col)\n const node = new Node(this.root, this, {\n childIndex: nodeIndex,\n order: rowIndex,\n col: columnIndex,\n height: this.defaultSize,\n })\n this.register(node)\n this.root.registerNode(node)\n }\n\n public pushNodes(count: number) {\n const { count: originalCount, col } = this\n for (let i = originalCount; i < originalCount + count; i++) {\n this.pushNode(i, col)\n }\n this.count += count\n this.root.lowerThresholdScrollTop = Infinity\n // 同步 section state.height,避免与 maxColumnHeight 不一致导致 footer 错位\n this.setStateIn('height', this.maxColumnHeight)\n this.updateNodes()\n this.updateBehindSectionsPosition()\n // 立即更新 scrollHeight,避免防抖导致容器高度滞后引发往上抖动\n this.root.updateScrollHeight(true)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -27,4 +27,8 @@ export declare const createImperativePromise: () => {
27
27
  reject: (reason?: any) => void;
28
28
  };
29
29
  export declare const isWeb: () => boolean;
30
+ /** 判断是否为 H5(用于 scrollElement 模式等) */
31
+ export declare const isH5: boolean;
32
+ /** 判断是否为微信小程序(用于 scrollElement 模式等) */
33
+ export declare const isWeapp: boolean;
30
34
  export {};
@@ -40,6 +40,10 @@ const createImperativePromise = () => {
40
40
  return Object.assign(Object.assign({}, handle), { promise });
41
41
  };
42
42
  const isWeb = () => getEnv().toLowerCase() === 'web';
43
+ /** 判断是否为 H5(用于 scrollElement 模式等) */
44
+ const isH5 = process.env.TARO_ENV === 'h5';
45
+ /** 判断是否为微信小程序(用于 scrollElement 模式等) */
46
+ const isWeapp = process.env.TARO_ENV === 'weapp';
43
47
 
44
- export { createImperativePromise, getMatrixPosition, getSysInfo, isSameRenderRange, isWeb };
48
+ export { createImperativePromise, getMatrixPosition, getSysInfo, isH5, isSameRenderRange, isWeapp, isWeb };
45
49
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/components/water-flow/utils.ts"],"sourcesContent":["import { getEnv, getSystemInfoSync } from '@tarojs/taro'\n\nlet sysInfo: ReturnType<typeof getSystemInfoSync>\n\nexport const getSysInfo = () => {\n if (sysInfo) return sysInfo\n sysInfo = getSystemInfoSync()\n return sysInfo\n}\n\ntype ArrIndex = number;\n/**\n * 一维数组索引换算到二维数组\n * @param i 一维数组索引\n * @param columns 列数\n */\nexport function getMatrixPosition(i: ArrIndex, columns: number) {\n const col = i % columns // 列号\n const row = Math.floor(i / columns) // 行号\n return { row, col }\n}\n\n/**\n * 简单比较渲染区间范围\n */\nexport function isSameRenderRange(a: any[], b: any[]) {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\n/**\n * 创建一个命令式的 promise 对象\n *\n * 返回的对象包含以下属性:\n * - promise: 一个新的 Promise 对象,初始状态为 pending。\n * - resolve: 一个函数,用于将 promise 状态置为 resolved。\n * - reject: 一个函数,用于将 promise 状态置为 rejected,并可以传递一个原因参数。\n */\nexport const createImperativePromise = () => {\n type ImperativePromiseHandle = {\n resolve: () => void\n reject: (reason?: any) => void\n };\n const handle = {} as ImperativePromiseHandle\n const promise = new Promise<void>((resolve, reject) => {\n handle.resolve = resolve\n handle.reject = reject\n })\n return {\n ...handle,\n promise,\n }\n}\n\nexport const isWeb = () => getEnv().toLowerCase() === 'web'\n"],"names":[],"mappings":";;AAEA,IAAI,OAA6C;AAE1C,MAAM,UAAU,GAAG,MAAK;AAC7B,IAAA,IAAI,OAAO;AAAE,QAAA,OAAO,OAAO;IAC3B,OAAO,GAAG,iBAAiB,EAAE;AAC7B,IAAA,OAAO,OAAO;AAChB;AAGA;;;;AAIG;AACa,SAAA,iBAAiB,CAAC,CAAW,EAAE,OAAe,EAAA;AAC5D,IAAA,MAAM,GAAG,GAAG,CAAC,GAAG,OAAO,CAAA;AACvB,IAAA,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAA;AACnC,IAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE;AACrB;AAEA;;AAEG;AACa,SAAA,iBAAiB,CAAC,CAAQ,EAAE,CAAQ,EAAA;AAClD,IAAA,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAChD;AAEA;;;;;;;AAOG;AACI,MAAM,uBAAuB,GAAG,MAAK;IAK1C,MAAM,MAAM,GAAG,EAA6B;IAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;AACpD,QAAA,MAAM,CAAC,OAAO,GAAG,OAAO;AACxB,QAAA,MAAM,CAAC,MAAM,GAAG,MAAM;AACxB,KAAC,CAAC;IACF,OACK,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAA,MAAM,CACT,EAAA,EAAA,OAAO,EACR,CAAA;AACH;AAEO,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAC,WAAW,EAAE,KAAK;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/components/water-flow/utils.ts"],"sourcesContent":["import { getEnv, getSystemInfoSync } from '@tarojs/taro'\n\nlet sysInfo: ReturnType<typeof getSystemInfoSync>\n\nexport const getSysInfo = () => {\n if (sysInfo) return sysInfo\n sysInfo = getSystemInfoSync()\n return sysInfo\n}\n\ntype ArrIndex = number;\n/**\n * 一维数组索引换算到二维数组\n * @param i 一维数组索引\n * @param columns 列数\n */\nexport function getMatrixPosition(i: ArrIndex, columns: number) {\n const col = i % columns // 列号\n const row = Math.floor(i / columns) // 行号\n return { row, col }\n}\n\n/**\n * 简单比较渲染区间范围\n */\nexport function isSameRenderRange(a: any[], b: any[]) {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\n/**\n * 创建一个命令式的 promise 对象\n *\n * 返回的对象包含以下属性:\n * - promise: 一个新的 Promise 对象,初始状态为 pending。\n * - resolve: 一个函数,用于将 promise 状态置为 resolved。\n * - reject: 一个函数,用于将 promise 状态置为 rejected,并可以传递一个原因参数。\n */\nexport const createImperativePromise = () => {\n type ImperativePromiseHandle = {\n resolve: () => void\n reject: (reason?: any) => void\n };\n const handle = {} as ImperativePromiseHandle\n const promise = new Promise<void>((resolve, reject) => {\n handle.resolve = resolve\n handle.reject = reject\n })\n return {\n ...handle,\n promise,\n }\n}\n\nexport const isWeb = () => getEnv().toLowerCase() === 'web'\n\n/** 判断是否为 H5(用于 scrollElement 模式等) */\nexport const isH5 = process.env.TARO_ENV === 'h5'\n\n/** 判断是否为微信小程序(用于 scrollElement 模式等) */\nexport const isWeapp = process.env.TARO_ENV === 'weapp'\n"],"names":[],"mappings":";;AAEA,IAAI,OAA6C;AAE1C,MAAM,UAAU,GAAG,MAAK;AAC7B,IAAA,IAAI,OAAO;AAAE,QAAA,OAAO,OAAO;IAC3B,OAAO,GAAG,iBAAiB,EAAE;AAC7B,IAAA,OAAO,OAAO;AAChB;AAGA;;;;AAIG;AACa,SAAA,iBAAiB,CAAC,CAAW,EAAE,OAAe,EAAA;AAC5D,IAAA,MAAM,GAAG,GAAG,CAAC,GAAG,OAAO,CAAA;AACvB,IAAA,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAA;AACnC,IAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE;AACrB;AAEA;;AAEG;AACa,SAAA,iBAAiB,CAAC,CAAQ,EAAE,CAAQ,EAAA;AAClD,IAAA,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAChD;AAEA;;;;;;;AAOG;AACI,MAAM,uBAAuB,GAAG,MAAK;IAK1C,MAAM,MAAM,GAAG,EAA6B;IAC5C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,KAAI;AACpD,QAAA,MAAM,CAAC,OAAO,GAAG,OAAO;AACxB,QAAA,MAAM,CAAC,MAAM,GAAG,MAAM;AACxB,KAAC,CAAC;IACF,OACK,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAA,MAAM,CACT,EAAA,EAAA,OAAO,EACR,CAAA;AACH;AAEO,MAAM,KAAK,GAAG,MAAM,MAAM,EAAE,CAAC,WAAW,EAAE,KAAK;AAEtD;AACa,MAAA,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;AAE7C;AACa,MAAA,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK;;;;"}