@tarojs/components-advanced 4.1.12-beta.43 → 4.1.12-beta.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/list/hooks/useListNestedScroll.d.ts +1 -1
- package/dist/components/list/hooks/useListNestedScroll.js +2 -2
- package/dist/components/list/hooks/useListNestedScroll.js.map +1 -1
- package/dist/components/list/hooks/useListScrollElementAttachWeapp.d.ts +2 -1
- package/dist/components/list/hooks/useListScrollElementAttachWeapp.js +7 -6
- package/dist/components/list/hooks/useListScrollElementAttachWeapp.js.map +1 -1
- package/dist/components/list/hooks/useMeasureStartOffsetWeapp.d.ts +4 -4
- package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js +30 -25
- package/dist/components/list/hooks/useMeasureStartOffsetWeapp.js.map +1 -1
- package/dist/components/list/hooks/useResizeObserver.d.ts +4 -2
- package/dist/components/list/hooks/useResizeObserver.js +7 -6
- package/dist/components/list/hooks/useResizeObserver.js.map +1 -1
- package/dist/components/list/index.d.ts +0 -2
- package/dist/components/list/index.js +7 -7
- package/dist/components/list/index.js.map +1 -1
- package/dist/components/list/utils.d.ts +11 -4
- package/dist/components/list/utils.js +18 -12
- package/dist/components/list/utils.js.map +1 -1
- package/dist/components/water-flow/flow-item.js +12 -7
- package/dist/components/water-flow/flow-item.js.map +1 -1
- package/dist/components/water-flow/node.d.ts +3 -0
- package/dist/components/water-flow/node.js +34 -1
- package/dist/components/water-flow/node.js.map +1 -1
- package/dist/components/water-flow/root.d.ts +4 -0
- package/dist/components/water-flow/root.js +37 -9
- package/dist/components/water-flow/root.js.map +1 -1
- package/dist/components/water-flow/section.d.ts +2 -0
- package/dist/components/water-flow/section.js +16 -9
- package/dist/components/water-flow/section.js.map +1 -1
- package/dist/components/water-flow/water-flow.js +26 -11
- package/dist/components/water-flow/water-flow.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/dom.d.ts +2 -2
- package/dist/utils/dom.js +7 -6
- package/dist/utils/dom.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/weapp-scope.d.ts +7 -0
- package/dist/utils/weapp-scope.js +20 -0
- package/dist/utils/weapp-scope.js.map +1 -0
- package/package.json +9 -9
|
@@ -15,4 +15,4 @@ export interface UseListNestedScrollResult {
|
|
|
15
15
|
/**
|
|
16
16
|
* 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析
|
|
17
17
|
*/
|
|
18
|
-
export declare function useListNestedScroll(listType: 'default' | 'nested', scrollElement?: RefObject<HTMLElement | null>, startOffsetProp?: number, isHorizontal?: boolean
|
|
18
|
+
export declare function useListNestedScroll(listType: 'default' | 'nested', scrollElement?: RefObject<HTMLElement | null>, startOffsetProp?: number, isHorizontal?: boolean): UseListNestedScrollResult;
|
|
@@ -9,7 +9,7 @@ const EMPTY_SCROLL_REF = { current: null };
|
|
|
9
9
|
/**
|
|
10
10
|
* 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析
|
|
11
11
|
*/
|
|
12
|
-
function useListNestedScroll(listType, scrollElement, startOffsetProp, isHorizontal = false
|
|
12
|
+
function useListNestedScroll(listType, scrollElement, startOffsetProp, isHorizontal = false) {
|
|
13
13
|
var _a, _b, _c, _d;
|
|
14
14
|
const contentWrapperRef = useRef(null);
|
|
15
15
|
const contentId = useMemo(() => `list-content-${Math.random().toString(36).slice(2, 11)}`, []);
|
|
@@ -34,7 +34,7 @@ function useListNestedScroll(listType, scrollElement, startOffsetProp, isHorizon
|
|
|
34
34
|
!hasExplicitCtxStartOffset;
|
|
35
35
|
const effectiveStartOffsetRef = useRef(0);
|
|
36
36
|
const measuredStartOffset = useMeasureStartOffset(effectiveScrollElement !== null && effectiveScrollElement !== void 0 ? effectiveScrollElement : EMPTY_SCROLL_REF, contentWrapperRef, { enabled: !!needMeasure, isHorizontal });
|
|
37
|
-
const measuredStartOffsetWeapp = useMeasureStartOffsetWeapp(effectiveScrollElement !== null && effectiveScrollElement !== void 0 ? effectiveScrollElement : EMPTY_SCROLL_REF, contentId, { enabled: !!needMeasureWeapp, isHorizontal, startOffsetRef: effectiveStartOffsetRef,
|
|
37
|
+
const measuredStartOffsetWeapp = useMeasureStartOffsetWeapp(effectiveScrollElement !== null && effectiveScrollElement !== void 0 ? effectiveScrollElement : EMPTY_SCROLL_REF, contentId, { enabled: !!needMeasureWeapp, isHorizontal, startOffsetRef: effectiveStartOffsetRef, contentWrapperRef });
|
|
38
38
|
const effectiveStartOffset = (_d = (_c = (_b = startOffsetProp !== null && startOffsetProp !== void 0 ? startOffsetProp : (ctxStart != null && ctxStart > 0 ? ctxStart : null)) !== null && _b !== void 0 ? _b : measuredStartOffset) !== null && _c !== void 0 ? _c : measuredStartOffsetWeapp) !== null && _d !== void 0 ? _d : 0;
|
|
39
39
|
// needMeasureWeapp 时由 useMeasureStartOffsetWeapp 的 exec 回调更新 ref,不在此覆盖,避免 re-render 用 stale 0 覆盖已测量的值
|
|
40
40
|
if (!needMeasureWeapp) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListNestedScroll.js","sources":["../../../../src/components/list/hooks/useListNestedScroll.ts"],"sourcesContent":["import React, { useContext, useMemo, useRef } from 'react'\n\nimport {\n type ScrollElementContextValueShape,\n ScrollElementContextOrFallback,\n} from '../../../utils/scrollElementContext'\nimport { isH5, isWeapp } from '../utils'\nimport { useMeasureStartOffset } from './useMeasureStartOffset'\nimport { useMeasureStartOffsetWeapp } from './useMeasureStartOffsetWeapp'\nimport { useScrollParentAutoFind } from './useScrollParentAutoFind'\n\nimport type { RefObject } from 'react'\n\nconst EMPTY_SCROLL_REF = { current: null as HTMLElement | null }\n\nexport interface UseListNestedScrollResult {\n effectiveScrollElement: RefObject<HTMLElement | null> | null\n effectiveStartOffset: number\n /** 小程序用:实时读取 startOffset,避免 useState 异步更新导致 useListScrollElementAttachWeapp 读到 0 */\n effectiveStartOffsetRef: React.MutableRefObject<number>\n useScrollElementMode: boolean\n needAutoFind: boolean\n autoFindStatus: 'pending' | 'found' | 'not-found'\n contentWrapperRef: RefObject<HTMLDivElement | null>\n /** 小程序自动查找用:content 节点的 id,需挂到 contentWrapper 对应的 View 上 */\n contentId: string\n}\n\n/**\n * 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析\n */\nexport function useListNestedScroll(\n listType: 'default' | 'nested',\n scrollElement?: RefObject<HTMLElement | null>,\n startOffsetProp?: number,\n isHorizontal: boolean = false
|
|
1
|
+
{"version":3,"file":"useListNestedScroll.js","sources":["../../../../src/components/list/hooks/useListNestedScroll.ts"],"sourcesContent":["import React, { useContext, useMemo, useRef } from 'react'\n\nimport {\n type ScrollElementContextValueShape,\n ScrollElementContextOrFallback,\n} from '../../../utils/scrollElementContext'\nimport { isH5, isWeapp } from '../utils'\nimport { useMeasureStartOffset } from './useMeasureStartOffset'\nimport { useMeasureStartOffsetWeapp } from './useMeasureStartOffsetWeapp'\nimport { useScrollParentAutoFind } from './useScrollParentAutoFind'\n\nimport type { RefObject } from 'react'\n\nconst EMPTY_SCROLL_REF = { current: null as HTMLElement | null }\n\nexport interface UseListNestedScrollResult {\n effectiveScrollElement: RefObject<HTMLElement | null> | null\n effectiveStartOffset: number\n /** 小程序用:实时读取 startOffset,避免 useState 异步更新导致 useListScrollElementAttachWeapp 读到 0 */\n effectiveStartOffsetRef: React.MutableRefObject<number>\n useScrollElementMode: boolean\n needAutoFind: boolean\n autoFindStatus: 'pending' | 'found' | 'not-found'\n contentWrapperRef: RefObject<HTMLDivElement | null>\n /** 小程序自动查找用:content 节点的 id,需挂到 contentWrapper 对应的 View 上 */\n contentId: string\n}\n\n/**\n * 合并嵌套滚动相关逻辑:Context、自动查找、startOffset 测量、scrollElement 解析\n */\nexport function useListNestedScroll(\n listType: 'default' | 'nested',\n scrollElement?: RefObject<HTMLElement | null>,\n startOffsetProp?: number,\n isHorizontal: boolean = false\n): UseListNestedScrollResult {\n const contentWrapperRef = useRef<HTMLDivElement>(null)\n const contentId = useMemo(() => `list-content-${Math.random().toString(36).slice(2, 11)}`, [])\n const scrollElementCtx = useContext(ScrollElementContextOrFallback) as ScrollElementContextValueShape | null\n const ctxStart = scrollElementCtx?.startOffset\n const hasExplicitCtxStartOffset = ctxStart != null && ctxStart > 0\n\n const needAutoFind =\n listType === 'nested' &&\n !scrollElement &&\n !scrollElementCtx?.scrollRef &&\n (isH5 || isWeapp)\n const { scrollParentRef: autoFoundRef, status: autoFindStatus } = useScrollParentAutoFind(\n contentWrapperRef,\n { enabled: !!needAutoFind, isHorizontal, contentId: isWeapp ? contentId : undefined }\n )\n\n const effectiveScrollElement =\n scrollElement ??\n scrollElementCtx?.scrollRef ??\n (needAutoFind && autoFindStatus === 'found' ? autoFoundRef : null)\n\n const needMeasure =\n listType === 'nested' &&\n effectiveScrollElement &&\n isH5 &&\n startOffsetProp == null &&\n !hasExplicitCtxStartOffset\n const needMeasureWeapp =\n listType === 'nested' &&\n effectiveScrollElement &&\n isWeapp &&\n startOffsetProp == null &&\n !hasExplicitCtxStartOffset\n const effectiveStartOffsetRef = useRef(0)\n const measuredStartOffset = useMeasureStartOffset(\n effectiveScrollElement ?? EMPTY_SCROLL_REF,\n contentWrapperRef,\n { enabled: !!needMeasure, isHorizontal }\n )\n const measuredStartOffsetWeapp = useMeasureStartOffsetWeapp(\n effectiveScrollElement ?? EMPTY_SCROLL_REF,\n contentId,\n { enabled: !!needMeasureWeapp, isHorizontal, startOffsetRef: effectiveStartOffsetRef, contentWrapperRef }\n )\n\n const effectiveStartOffset =\n startOffsetProp ??\n (ctxStart != null && ctxStart > 0 ? ctxStart : null) ??\n measuredStartOffset ??\n measuredStartOffsetWeapp ??\n 0\n\n // needMeasureWeapp 时由 useMeasureStartOffsetWeapp 的 exec 回调更新 ref,不在此覆盖,避免 re-render 用 stale 0 覆盖已测量的值\n if (!needMeasureWeapp) {\n effectiveStartOffsetRef.current = effectiveStartOffset\n }\n\n const useScrollElementMode = listType === 'nested' && !!(effectiveScrollElement && (isH5 || isWeapp))\n\n if (listType === 'nested' && !effectiveScrollElement && (isH5 || isWeapp) && autoFindStatus === 'not-found') {\n // eslint-disable-next-line no-console\n console.warn('[List] nestedScroll 模式但无 scrollElement(props/Context/自动查找),回退为 default')\n }\n\n return {\n effectiveScrollElement,\n effectiveStartOffset,\n effectiveStartOffsetRef,\n useScrollElementMode,\n needAutoFind,\n autoFindStatus,\n contentWrapperRef,\n contentId,\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,10 @@ import type { ListScrollElementAttachRefs } from './useListScrollElementAttach';
|
|
|
6
6
|
*
|
|
7
7
|
* 与 H5 版 useListScrollElementAttach 的区别:
|
|
8
8
|
* - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)
|
|
9
|
+
* - SelectorQuery 使用 `createSelectorQueryForRef(effectiveScrollElement)`,由滚动容器 ref 的 `_scope` 推导 `.in`,无需业务传 scope
|
|
9
10
|
* - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)
|
|
10
11
|
* - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用
|
|
11
12
|
*/
|
|
12
13
|
export declare function useListScrollElementAttachWeapp(enabled: boolean, effectiveScrollElement: RefObject<HTMLElement | null> | null, effectiveStartOffsetRef: MutableRefObject<number>, effectiveStartOffset: number, isHorizontal: boolean, setContainerLength: (v: number) => void, updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void, scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined, refsRef: RefObject<ListScrollElementAttachRefs>,
|
|
13
14
|
/** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */
|
|
14
|
-
fallbackContainerLength?: number
|
|
15
|
+
fallbackContainerLength?: number): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useRef, useEffect } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { createSelectorQueryForRef } from '../utils.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,
|
|
@@ -7,12 +7,13 @@ import { createSelectorQueryScoped } from '../utils.js';
|
|
|
7
7
|
*
|
|
8
8
|
* 与 H5 版 useListScrollElementAttach 的区别:
|
|
9
9
|
* - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)
|
|
10
|
+
* - SelectorQuery 使用 `createSelectorQueryForRef(effectiveScrollElement)`,由滚动容器 ref 的 `_scope` 推导 `.in`,无需业务传 scope
|
|
10
11
|
* - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)
|
|
11
12
|
* - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用
|
|
12
13
|
*/
|
|
13
14
|
function useListScrollElementAttachWeapp(enabled, effectiveScrollElement, effectiveStartOffsetRef, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, refsRef,
|
|
14
15
|
/** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */
|
|
15
|
-
fallbackContainerLength
|
|
16
|
+
fallbackContainerLength) {
|
|
16
17
|
const containerLengthRef = useRef(0);
|
|
17
18
|
const autoIdRef = useRef(`_ls_${Math.random().toString(36).slice(2, 9)}`);
|
|
18
19
|
useEffect(() => {
|
|
@@ -28,7 +29,7 @@ fallbackContainerLength, selectorQueryScope) {
|
|
|
28
29
|
}
|
|
29
30
|
const scrollViewId = el.id;
|
|
30
31
|
const measure = () => {
|
|
31
|
-
const query =
|
|
32
|
+
const query = createSelectorQueryForRef(effectiveScrollElement);
|
|
32
33
|
query
|
|
33
34
|
.select(`#${scrollViewId}`)
|
|
34
35
|
.boundingClientRect()
|
|
@@ -52,7 +53,7 @@ fallbackContainerLength, selectorQueryScope) {
|
|
|
52
53
|
measure();
|
|
53
54
|
const interval = setInterval(measure, 150);
|
|
54
55
|
return () => clearInterval(interval);
|
|
55
|
-
}, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength
|
|
56
|
+
}, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength]);
|
|
56
57
|
useEffect(() => {
|
|
57
58
|
if (!enabled || !effectiveScrollElement)
|
|
58
59
|
return;
|
|
@@ -108,7 +109,7 @@ fallbackContainerLength, selectorQueryScope) {
|
|
|
108
109
|
const scrollViewId = target.id || autoIdRef.current;
|
|
109
110
|
if (!target.id)
|
|
110
111
|
target.id = scrollViewId;
|
|
111
|
-
const query =
|
|
112
|
+
const query = createSelectorQueryForRef(effectiveScrollElement);
|
|
112
113
|
query.select(`#${scrollViewId}`).scrollOffset().exec((res) => {
|
|
113
114
|
var _a, _b;
|
|
114
115
|
const info = res === null || res === void 0 ? void 0 : res[0];
|
|
@@ -127,7 +128,7 @@ fallbackContainerLength, selectorQueryScope) {
|
|
|
127
128
|
cancelled = true;
|
|
128
129
|
teardown === null || teardown === void 0 ? void 0 : teardown();
|
|
129
130
|
};
|
|
130
|
-
}, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength
|
|
131
|
+
}, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength]);
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
export { useListScrollElementAttachWeapp };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListScrollElementAttachWeapp.js","sources":["../../../../src/components/list/hooks/useListScrollElementAttachWeapp.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport { createSelectorQueryScoped } from '../utils'\n\nimport type { MutableRefObject, RefObject } from 'react'\nimport type { ListScrollElementAttachRefs } from './useListScrollElementAttach'\n\n/**\n * 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,\n * 并通过 createSelectorQuery 测量容器尺寸。\n *\n * 与 H5 版 useListScrollElementAttach 的区别:\n * - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)\n * - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)\n * - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用\n */\nexport function useListScrollElementAttachWeapp(\n enabled: boolean,\n effectiveScrollElement: RefObject<HTMLElement | null> | null,\n effectiveStartOffsetRef: MutableRefObject<number>,\n effectiveStartOffset: number,\n isHorizontal: boolean,\n setContainerLength: (v: number) => void,\n updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void,\n scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined,\n refsRef: RefObject<ListScrollElementAttachRefs>,\n /** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */\n fallbackContainerLength?: number,\n selectorQueryScope?: object\n) {\n const containerLengthRef = useRef(0)\n const autoIdRef = useRef(`_ls_${Math.random().toString(36).slice(2, 9)}`)\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n const el = effectiveScrollElement.current as any\n if (!el) return\n if (scrollRefProp) scrollRefProp.current = el\n\n if (!el.id) {\n el.id = autoIdRef.current\n }\n const scrollViewId = el.id\n\n const measure = () => {\n const query = createSelectorQueryScoped(selectorQueryScope)\n query\n .select(`#${scrollViewId}`)\n .boundingClientRect()\n .exec((res) => {\n const rect = res?.[0]\n if (rect) {\n const measured = isHorizontal ? rect.width : rect.height\n if (measured > 0) {\n containerLengthRef.current = measured\n setContainerLength(measured)\n return\n }\n }\n // 兜底:rect 为空或 measured≤0 时,使用 fallback 避免 containerLengthRef 长期为 0\n if (fallbackContainerLength != null && fallbackContainerLength > 0) {\n containerLengthRef.current = fallbackContainerLength\n setContainerLength(fallbackContainerLength)\n }\n })\n }\n\n measure()\n const interval = setInterval(measure, 150)\n return () => clearInterval(interval)\n }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength, selectorQueryScope])\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n\n let cancelled = false\n let teardown: (() => void) | null = null\n const maxRetries = 20\n\n const tryAttach = (retryCount = 0) => {\n if (cancelled) return\n const target = effectiveScrollElement.current as any\n if (!target) {\n if (retryCount < maxRetries) {\n setTimeout(() => tryAttach(retryCount + 1), 50)\n }\n return\n }\n\n let inUpperZone = true\n let inLowerZone = false\n\n const handler = (e: any) => {\n const r = refsRef.current\n if (!r) return\n\n const scrollPos = isHorizontal\n ? (e?.target?.scrollLeft ?? e?.mpEvent?.detail?.scrollLeft ?? 0)\n : (e?.target?.scrollTop ?? e?.mpEvent?.detail?.scrollTop ?? 0)\n const startOffset = effectiveStartOffsetRef.current\n const adjustedPos = scrollPos - startOffset\n const effectiveAdjusted = Math.max(0, adjustedPos)\n\n r.scrollCorrection.markUserScrolling()\n updateRenderOffset(effectiveAdjusted, false, 'scrollElement')\n const scrollTop = isHorizontal ? 0 : scrollPos\n const scrollLeft = isHorizontal ? scrollPos : 0\n r.onScroll?.({ scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } })\n\n // 兜底:measure 未完成时 containerLengthRef 为 0,用 fallback 参与触顶/触底判断,避免漏触发\n const clientSize = containerLengthRef.current || fallbackContainerLength || 0\n if (clientSize > 0) {\n const { upper, lower } = r.threshold\n const innerContentLen = r.listContentLength\n const nowInUpper = effectiveAdjusted <= upper\n const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower\n if (nowInUpper && !inUpperZone) r.onScrollToUpper?.()\n if (nowInLower && !inLowerZone) r.onScrollToLower?.()\n inUpperZone = nowInUpper\n inLowerZone = nowInLower\n }\n }\n\n target.addEventListener('scroll', handler)\n teardown = () => target.removeEventListener('scroll', handler)\n\n // 初始 renderOffset:weapp 无法直接读 target.scrollTop,需通过 SelectorQuery 查询\n const scrollViewId = target.id || autoIdRef.current\n if (!target.id) target.id = scrollViewId\n const query = createSelectorQueryScoped(selectorQueryScope)\n query.select(`#${scrollViewId}`).scrollOffset().exec((res) => {\n const info = res?.[0]\n if (info) {\n const scrollTopVal = info.scrollTop ?? 0\n const scrollLeftVal = info.scrollLeft ?? 0\n const scrollPos = isHorizontal ? scrollLeftVal : scrollTopVal\n const startOffset = effectiveStartOffsetRef.current\n const initialAdjusted = Math.max(0, scrollPos - startOffset)\n updateRenderOffset(initialAdjusted, false, 'scrollElement')\n }\n })\n }\n\n tryAttach()\n return () => {\n cancelled = true\n teardown?.()\n }\n }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength, selectorQueryScope])\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useListScrollElementAttachWeapp.js","sources":["../../../../src/components/list/hooks/useListScrollElementAttachWeapp.ts"],"sourcesContent":["import { useEffect, useRef } from 'react'\n\nimport { createSelectorQueryForRef } from '../utils'\n\nimport type { MutableRefObject, RefObject } from 'react'\nimport type { ListScrollElementAttachRefs } from './useListScrollElementAttach'\n\n/**\n * 小程序版 scrollElement 模式:监听外部 scroll-view 的滚动事件驱动 renderOffset,\n * 并通过 createSelectorQuery 测量容器尺寸。\n *\n * 与 H5 版 useListScrollElementAttach 的区别:\n * - 容器尺寸通过 createSelectorQuery 测量(无 ResizeObserver)\n * - SelectorQuery 使用 `createSelectorQueryForRef(effectiveScrollElement)`,由滚动容器 ref 的 `_scope` 推导 `.in`,无需业务传 scope\n * - 滚动事件通过 TaroElement.addEventListener,格式为 TaroEvent(detail 合并到 target 上)\n * - 若 scroll-view 无 id,自动分配临时 id 供 SelectorQuery 使用\n */\nexport function useListScrollElementAttachWeapp(\n enabled: boolean,\n effectiveScrollElement: RefObject<HTMLElement | null> | null,\n effectiveStartOffsetRef: MutableRefObject<number>,\n effectiveStartOffset: number,\n isHorizontal: boolean,\n setContainerLength: (v: number) => void,\n updateRenderOffset: (offset: number, sync?: boolean, source?: string) => void,\n scrollRefProp: React.MutableRefObject<HTMLElement | null> | undefined,\n refsRef: RefObject<ListScrollElementAttachRefs>,\n /** 测量未就绪或失败时的容器长度兜底,宜与 initialContainerLength 一致 */\n fallbackContainerLength?: number\n) {\n const containerLengthRef = useRef(0)\n const autoIdRef = useRef(`_ls_${Math.random().toString(36).slice(2, 9)}`)\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n const el = effectiveScrollElement.current as any\n if (!el) return\n if (scrollRefProp) scrollRefProp.current = el\n\n if (!el.id) {\n el.id = autoIdRef.current\n }\n const scrollViewId = el.id\n\n const measure = () => {\n const query = createSelectorQueryForRef(effectiveScrollElement)\n query\n .select(`#${scrollViewId}`)\n .boundingClientRect()\n .exec((res) => {\n const rect = res?.[0]\n if (rect) {\n const measured = isHorizontal ? rect.width : rect.height\n if (measured > 0) {\n containerLengthRef.current = measured\n setContainerLength(measured)\n return\n }\n }\n // 兜底:rect 为空或 measured≤0 时,使用 fallback 避免 containerLengthRef 长期为 0\n if (fallbackContainerLength != null && fallbackContainerLength > 0) {\n containerLengthRef.current = fallbackContainerLength\n setContainerLength(fallbackContainerLength)\n }\n })\n }\n\n measure()\n const interval = setInterval(measure, 150)\n return () => clearInterval(interval)\n }, [enabled, effectiveScrollElement, isHorizontal, scrollRefProp, setContainerLength, fallbackContainerLength])\n\n useEffect(() => {\n if (!enabled || !effectiveScrollElement) return\n\n let cancelled = false\n let teardown: (() => void) | null = null\n const maxRetries = 20\n\n const tryAttach = (retryCount = 0) => {\n if (cancelled) return\n const target = effectiveScrollElement.current as any\n if (!target) {\n if (retryCount < maxRetries) {\n setTimeout(() => tryAttach(retryCount + 1), 50)\n }\n return\n }\n\n let inUpperZone = true\n let inLowerZone = false\n\n const handler = (e: any) => {\n const r = refsRef.current\n if (!r) return\n\n const scrollPos = isHorizontal\n ? (e?.target?.scrollLeft ?? e?.mpEvent?.detail?.scrollLeft ?? 0)\n : (e?.target?.scrollTop ?? e?.mpEvent?.detail?.scrollTop ?? 0)\n const startOffset = effectiveStartOffsetRef.current\n const adjustedPos = scrollPos - startOffset\n const effectiveAdjusted = Math.max(0, adjustedPos)\n\n r.scrollCorrection.markUserScrolling()\n updateRenderOffset(effectiveAdjusted, false, 'scrollElement')\n const scrollTop = isHorizontal ? 0 : scrollPos\n const scrollLeft = isHorizontal ? scrollPos : 0\n r.onScroll?.({ scrollTop, scrollLeft, detail: { scrollTop, scrollLeft } })\n\n // 兜底:measure 未完成时 containerLengthRef 为 0,用 fallback 参与触顶/触底判断,避免漏触发\n const clientSize = containerLengthRef.current || fallbackContainerLength || 0\n if (clientSize > 0) {\n const { upper, lower } = r.threshold\n const innerContentLen = r.listContentLength\n const nowInUpper = effectiveAdjusted <= upper\n const nowInLower = innerContentLen > 0 && effectiveAdjusted + clientSize >= innerContentLen - lower\n if (nowInUpper && !inUpperZone) r.onScrollToUpper?.()\n if (nowInLower && !inLowerZone) r.onScrollToLower?.()\n inUpperZone = nowInUpper\n inLowerZone = nowInLower\n }\n }\n\n target.addEventListener('scroll', handler)\n teardown = () => target.removeEventListener('scroll', handler)\n\n // 初始 renderOffset:weapp 无法直接读 target.scrollTop,需通过 SelectorQuery 查询\n const scrollViewId = target.id || autoIdRef.current\n if (!target.id) target.id = scrollViewId\n const query = createSelectorQueryForRef(effectiveScrollElement)\n query.select(`#${scrollViewId}`).scrollOffset().exec((res) => {\n const info = res?.[0]\n if (info) {\n const scrollTopVal = info.scrollTop ?? 0\n const scrollLeftVal = info.scrollLeft ?? 0\n const scrollPos = isHorizontal ? scrollLeftVal : scrollTopVal\n const startOffset = effectiveStartOffsetRef.current\n const initialAdjusted = Math.max(0, scrollPos - startOffset)\n updateRenderOffset(initialAdjusted, false, 'scrollElement')\n }\n })\n }\n\n tryAttach()\n return () => {\n cancelled = true\n teardown?.()\n }\n }, [enabled, effectiveScrollElement, isHorizontal, effectiveStartOffsetRef, effectiveStartOffset, updateRenderOffset, refsRef, fallbackContainerLength])\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { MutableRefObject, RefObject } from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* 小程序版 startOffset
|
|
4
|
-
*
|
|
3
|
+
* 小程序版 startOffset:对外层 scroll-view 与带 `contentId` 的外包各执行一次 SelectorQuery(各自 `weappScope(ref)`),
|
|
4
|
+
* 再合并结果;避免二者不在同一自定义组件时,单次 `in` 链式 `select` 查不全。
|
|
5
5
|
*
|
|
6
6
|
* 公式:startOffset = contentRect.top - scrollRect.top + scrollTop
|
|
7
|
-
* (content 在屏幕上的 top - scroll 可视区 top + 已滚动距离)
|
|
8
7
|
*/
|
|
9
8
|
export declare function useMeasureStartOffsetWeapp(scrollElRef: RefObject<HTMLElement | null>, contentId: string, options: {
|
|
10
9
|
enabled: boolean;
|
|
11
10
|
isHorizontal?: boolean;
|
|
12
11
|
startOffsetRef?: MutableRefObject<number>;
|
|
13
|
-
|
|
12
|
+
/** 挂载 `id={contentId}` 的嵌套内容外包 View;第二次 query 用其 ref 取 content 侧 `_scope` */
|
|
13
|
+
contentWrapperRef: RefObject<HTMLElement | null>;
|
|
14
14
|
}): number;
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { useState, useRef, useEffect } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { createSelectorQueryForRef } from '../utils.js';
|
|
3
3
|
|
|
4
4
|
const MAX_RETRY = 20;
|
|
5
5
|
const RETRY_DELAY = 50;
|
|
6
6
|
/** 与 useListScrollElementAttachWeapp 容器测量间隔一致(H5 无 interval,用 ResizeObserver+scroll 事件驱动) */
|
|
7
7
|
const MEASURE_INTERVAL = 150;
|
|
8
8
|
/**
|
|
9
|
-
* 小程序版 startOffset
|
|
10
|
-
*
|
|
9
|
+
* 小程序版 startOffset:对外层 scroll-view 与带 `contentId` 的外包各执行一次 SelectorQuery(各自 `weappScope(ref)`),
|
|
10
|
+
* 再合并结果;避免二者不在同一自定义组件时,单次 `in` 链式 `select` 查不全。
|
|
11
11
|
*
|
|
12
12
|
* 公式:startOffset = contentRect.top - scrollRect.top + scrollTop
|
|
13
|
-
* (content 在屏幕上的 top - scroll 可视区 top + 已滚动距离)
|
|
14
13
|
*/
|
|
15
14
|
function useMeasureStartOffsetWeapp(scrollElRef, contentId, options) {
|
|
16
|
-
const { enabled, isHorizontal = false, startOffsetRef,
|
|
15
|
+
const { enabled, isHorizontal = false, startOffsetRef, contentWrapperRef } = options;
|
|
17
16
|
const [measuredStartOffset, setMeasuredStartOffset] = useState(0);
|
|
18
17
|
const [retryTrigger, setRetryTrigger] = useState(0);
|
|
19
18
|
const retryCountRef = useRef(0);
|
|
@@ -23,6 +22,19 @@ function useMeasureStartOffsetWeapp(scrollElRef, contentId, options) {
|
|
|
23
22
|
retryCountRef.current = 0;
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
25
|
+
const applyRects = (scrollRect, scrollInfo, contentRect) => {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
if (!scrollRect || !scrollInfo || !contentRect)
|
|
28
|
+
return;
|
|
29
|
+
const scrollTop = (_a = scrollInfo.scrollTop) !== null && _a !== void 0 ? _a : 0;
|
|
30
|
+
const scrollLeft = (_b = scrollInfo.scrollLeft) !== null && _b !== void 0 ? _b : 0;
|
|
31
|
+
const value = isHorizontal
|
|
32
|
+
? Math.max(0, contentRect.left - scrollRect.left + scrollLeft)
|
|
33
|
+
: Math.max(0, contentRect.top - scrollRect.top + scrollTop);
|
|
34
|
+
if (startOffsetRef)
|
|
35
|
+
startOffsetRef.current = value;
|
|
36
|
+
setMeasuredStartOffset((prevVal) => (Math.abs(prevVal - value) < 1 ? prevVal : value));
|
|
37
|
+
};
|
|
26
38
|
const measure = () => {
|
|
27
39
|
const scrollEl = scrollElRef.current;
|
|
28
40
|
if (!scrollEl)
|
|
@@ -31,28 +43,23 @@ function useMeasureStartOffsetWeapp(scrollElRef, contentId, options) {
|
|
|
31
43
|
scrollEl.id = autoIdRef.current;
|
|
32
44
|
}
|
|
33
45
|
const scrollViewId = scrollEl.id;
|
|
34
|
-
|
|
35
|
-
query
|
|
46
|
+
createSelectorQueryForRef(scrollElRef)
|
|
36
47
|
.select(`#${scrollViewId}`)
|
|
37
48
|
.boundingClientRect()
|
|
38
49
|
.select(`#${scrollViewId}`)
|
|
39
50
|
.scrollOffset()
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const scrollRect = res === null || res === void 0 ? void 0 : res[0];
|
|
45
|
-
const scrollInfo = res === null || res === void 0 ? void 0 : res[1];
|
|
46
|
-
const contentRect = res === null || res === void 0 ? void 0 : res[2];
|
|
47
|
-
if (!scrollRect || !scrollInfo || !contentRect)
|
|
51
|
+
.exec((scrollRes) => {
|
|
52
|
+
const scrollRect = scrollRes === null || scrollRes === void 0 ? void 0 : scrollRes[0];
|
|
53
|
+
const scrollInfo = scrollRes === null || scrollRes === void 0 ? void 0 : scrollRes[1];
|
|
54
|
+
if (!scrollRect || !scrollInfo)
|
|
48
55
|
return;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
createSelectorQueryForRef(contentWrapperRef)
|
|
57
|
+
.select(`#${contentId}`)
|
|
58
|
+
.boundingClientRect()
|
|
59
|
+
.exec((contentRes) => {
|
|
60
|
+
const contentRect = contentRes === null || contentRes === void 0 ? void 0 : contentRes[0];
|
|
61
|
+
applyRects(scrollRect, scrollInfo, contentRect);
|
|
62
|
+
});
|
|
56
63
|
});
|
|
57
64
|
};
|
|
58
65
|
const scrollEl = scrollElRef.current;
|
|
@@ -66,15 +73,13 @@ function useMeasureStartOffsetWeapp(scrollElRef, contentId, options) {
|
|
|
66
73
|
}
|
|
67
74
|
retryCountRef.current = 0;
|
|
68
75
|
measure();
|
|
69
|
-
// 对标 H5:scroll 时触发测量(H5 用 scrollEl.addEventListener('scroll', measure))
|
|
70
76
|
scrollEl.addEventListener('scroll', measure);
|
|
71
|
-
// 无 ResizeObserver,用 interval 兜底布局变化
|
|
72
77
|
const interval = setInterval(measure, MEASURE_INTERVAL);
|
|
73
78
|
return () => {
|
|
74
79
|
scrollEl.removeEventListener('scroll', measure);
|
|
75
80
|
clearInterval(interval);
|
|
76
81
|
};
|
|
77
|
-
}, [enabled, scrollElRef, contentId, isHorizontal, retryTrigger
|
|
82
|
+
}, [enabled, scrollElRef, contentId, contentWrapperRef, isHorizontal, retryTrigger]);
|
|
78
83
|
return measuredStartOffset;
|
|
79
84
|
}
|
|
80
85
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMeasureStartOffsetWeapp.js","sources":["../../../../src/components/list/hooks/useMeasureStartOffsetWeapp.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\nimport {
|
|
1
|
+
{"version":3,"file":"useMeasureStartOffsetWeapp.js","sources":["../../../../src/components/list/hooks/useMeasureStartOffsetWeapp.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\nimport { createSelectorQueryForRef } from '../utils'\n\nimport type { MutableRefObject, RefObject } from 'react'\n\nconst MAX_RETRY = 20\nconst RETRY_DELAY = 50\n/** 与 useListScrollElementAttachWeapp 容器测量间隔一致(H5 无 interval,用 ResizeObserver+scroll 事件驱动) */\nconst MEASURE_INTERVAL = 150\n\n/**\n * 小程序版 startOffset:对外层 scroll-view 与带 `contentId` 的外包各执行一次 SelectorQuery(各自 `weappScope(ref)`),\n * 再合并结果;避免二者不在同一自定义组件时,单次 `in` 链式 `select` 查不全。\n *\n * 公式:startOffset = contentRect.top - scrollRect.top + scrollTop\n */\nexport function useMeasureStartOffsetWeapp(\n scrollElRef: RefObject<HTMLElement | null>,\n contentId: string,\n options: {\n enabled: boolean\n isHorizontal?: boolean\n startOffsetRef?: MutableRefObject<number>\n /** 挂载 `id={contentId}` 的嵌套内容外包 View;第二次 query 用其 ref 取 content 侧 `_scope` */\n contentWrapperRef: RefObject<HTMLElement | null>\n }\n): number {\n const { enabled, isHorizontal = false, startOffsetRef, contentWrapperRef } = options\n const [measuredStartOffset, setMeasuredStartOffset] = useState(0)\n const [retryTrigger, setRetryTrigger] = useState(0)\n const retryCountRef = useRef(0)\n const autoIdRef = useRef(`_ls_so_${Math.random().toString(36).slice(2, 9)}`)\n\n useEffect(() => {\n if (!enabled || !contentId) {\n retryCountRef.current = 0\n return\n }\n\n const applyRects = (scrollRect: any, scrollInfo: any, contentRect: any) => {\n if (!scrollRect || !scrollInfo || !contentRect) return\n const scrollTop = scrollInfo.scrollTop ?? 0\n const scrollLeft = scrollInfo.scrollLeft ?? 0\n const value = isHorizontal\n ? Math.max(0, contentRect.left - scrollRect.left + scrollLeft)\n : Math.max(0, contentRect.top - scrollRect.top + scrollTop)\n if (startOffsetRef) startOffsetRef.current = value\n setMeasuredStartOffset((prevVal) => (Math.abs(prevVal - value) < 1 ? prevVal : value))\n }\n\n const measure = () => {\n const scrollEl = scrollElRef.current as any\n if (!scrollEl) return\n\n if (!scrollEl.id) {\n scrollEl.id = autoIdRef.current\n }\n const scrollViewId = scrollEl.id\n\n createSelectorQueryForRef(scrollElRef)\n .select(`#${scrollViewId}`)\n .boundingClientRect()\n .select(`#${scrollViewId}`)\n .scrollOffset()\n .exec((scrollRes) => {\n const scrollRect = scrollRes?.[0]\n const scrollInfo = scrollRes?.[1]\n if (!scrollRect || !scrollInfo) return\n createSelectorQueryForRef(contentWrapperRef)\n .select(`#${contentId}`)\n .boundingClientRect()\n .exec((contentRes) => {\n const contentRect = contentRes?.[0]\n applyRects(scrollRect, scrollInfo, contentRect)\n })\n })\n }\n\n const scrollEl = scrollElRef.current\n if (!scrollEl) {\n if (retryCountRef.current < MAX_RETRY) {\n retryCountRef.current += 1\n const id = setTimeout(() => setRetryTrigger((t) => t + 1), RETRY_DELAY)\n return () => clearTimeout(id)\n }\n return\n }\n retryCountRef.current = 0\n measure()\n scrollEl.addEventListener('scroll', measure)\n const interval = setInterval(measure, MEASURE_INTERVAL)\n return () => {\n scrollEl.removeEventListener('scroll', measure)\n clearInterval(interval)\n }\n }, [enabled, scrollElRef, contentId, contentWrapperRef, isHorizontal, retryTrigger])\n\n return measuredStartOffset\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
1
2
|
/**
|
|
2
3
|
* useResizeObserver Hook - 尺寸变化监听(平台适配)
|
|
3
4
|
*
|
|
@@ -9,9 +10,10 @@ interface UseResizeObserverOptions {
|
|
|
9
10
|
enabled: boolean;
|
|
10
11
|
/** 是否水平滚动(监听 width 还是 height) */
|
|
11
12
|
isHorizontal: boolean;
|
|
12
|
-
/**
|
|
13
|
+
/** 小程序:ScrollView 上的随机 id 段(`id={listId}`),用于 `relativeTo('#'+listId)` 及 `#${listId}-list-item-inner-*` 等选择器 */
|
|
13
14
|
listId: string;
|
|
14
|
-
|
|
15
|
+
/** 小程序:应指向带 `listId` 的 ScrollView;仅解析 IO 的组件实例(`weappScope`),不作为 `relativeTo` 的参数传入 */
|
|
16
|
+
listViewportRef: RefObject<HTMLElement | null>;
|
|
15
17
|
/** 尺寸变化回调 */
|
|
16
18
|
onResize: (index: number, size: number) => void;
|
|
17
19
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import Taro from '@tarojs/taro';
|
|
2
2
|
import { useRef, useCallback, useEffect } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { getIntersectionObserverScopeForRef, createSelectorQueryForRef, isH5, isMiniProgram } from '../utils.js';
|
|
4
4
|
|
|
5
5
|
function useResizeObserver(options) {
|
|
6
|
-
const { enabled, isHorizontal, listId,
|
|
6
|
+
const { enabled, isHorizontal, listId, listViewportRef, onResize } = options;
|
|
7
7
|
// H5: ResizeObserver 实例
|
|
8
8
|
const observerRef = useRef(null);
|
|
9
9
|
// 小程序: IntersectionObserver 实例 Map
|
|
@@ -55,16 +55,17 @@ function useResizeObserver(options) {
|
|
|
55
55
|
: `#${listId}-list-header-inner-${-index - 1}`;
|
|
56
56
|
const doObserve = () => {
|
|
57
57
|
try {
|
|
58
|
-
const observerScope =
|
|
58
|
+
const observerScope = getIntersectionObserverScopeForRef(listViewportRef);
|
|
59
59
|
const observer = Taro.createIntersectionObserver(observerScope, {
|
|
60
60
|
observeAll: true
|
|
61
61
|
});
|
|
62
|
-
//
|
|
62
|
+
// 参照视口:仍为 `#${listId}` 字符串;与 `listViewportRef` 无 API 耦合,后者只影响上面 `createIntersectionObserver` 的首参
|
|
63
63
|
observer.relativeTo(`#${listId}`);
|
|
64
64
|
// 观察元素进入可见区域(唯一 id 避免跨 List 误命中)
|
|
65
65
|
observer.observe(selector, (res) => {
|
|
66
66
|
if (res.intersectionRatio > 0) {
|
|
67
|
-
|
|
67
|
+
// 与 observe 目标同一节点,SelectorQuery 的 in(scope) 与该节点 _scope 一致
|
|
68
|
+
createSelectorQueryForRef({ current: _element })
|
|
68
69
|
.select(selector)
|
|
69
70
|
.boundingClientRect((rect) => {
|
|
70
71
|
if (rect) {
|
|
@@ -82,7 +83,7 @@ function useResizeObserver(options) {
|
|
|
82
83
|
}
|
|
83
84
|
};
|
|
84
85
|
Taro.nextTick(doObserve);
|
|
85
|
-
}, [enabled, isHorizontal, listId,
|
|
86
|
+
}, [enabled, isHorizontal, listId, listViewportRef, onResize]);
|
|
86
87
|
/**
|
|
87
88
|
* 观察元素(平台自动适配)
|
|
88
89
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResizeObserver.js","sources":["../../../../src/components/list/hooks/useResizeObserver.ts"],"sourcesContent":["import Taro from '@tarojs/taro'\nimport { useCallback, useEffect, useRef } from 'react'\n\nimport {
|
|
1
|
+
{"version":3,"file":"useResizeObserver.js","sources":["../../../../src/components/list/hooks/useResizeObserver.ts"],"sourcesContent":["import Taro from '@tarojs/taro'\nimport { useCallback, useEffect, useRef } from 'react'\n\nimport { createSelectorQueryForRef, getIntersectionObserverScopeForRef, isH5, isMiniProgram } from '../utils'\n\nimport type { RefObject } from 'react'\n\n/**\n * useResizeObserver Hook - 尺寸变化监听(平台适配)\n *\n * H5: 使用 ResizeObserver API\n * 小程序: 使用 IntersectionObserver + SelectorQuery\n */\n\ninterface UseResizeObserverOptions {\n /** 是否启用监听 */\n enabled: boolean\n\n /** 是否水平滚动(监听 width 还是 height) */\n isHorizontal: boolean\n\n /** 小程序:ScrollView 上的随机 id 段(`id={listId}`),用于 `relativeTo('#'+listId)` 及 `#${listId}-list-item-inner-*` 等选择器 */\n listId: string\n\n /** 小程序:应指向带 `listId` 的 ScrollView;仅解析 IO 的组件实例(`weappScope`),不作为 `relativeTo` 的参数传入 */\n listViewportRef: RefObject<HTMLElement | null>\n\n /** 尺寸变化回调 */\n onResize: (index: number, size: number) => void\n}\n\ninterface UseResizeObserverReturn {\n /** 观察指定元素(传入 ref 和索引) */\n observe: (element: HTMLElement | null, index: number) => void\n\n /** 取消观察指定元素 */\n unobserve: (element: HTMLElement | null) => void\n\n /** 断开所有观察 */\n disconnect: () => void\n}\n\nexport function useResizeObserver(\n options: UseResizeObserverOptions\n): UseResizeObserverReturn {\n const { enabled, isHorizontal, listId, listViewportRef, onResize } = options\n\n // H5: ResizeObserver 实例\n const observerRef = useRef<ResizeObserver | null>(null)\n\n // 小程序: IntersectionObserver 实例 Map\n const intersectionObserversRef = useRef<Map<number, Taro.IntersectionObserver>>(new Map())\n\n // 已观察的元素 Map(用于去重)\n const observedElementsRef = useRef<Map<number, HTMLElement | null>>(new Map())\n\n /**\n * H5 实现:使用 ResizeObserver\n */\n const observeH5 = useCallback((element: HTMLElement | null, index: number) => {\n if (!element || !enabled) return\n\n // 避免重复观察\n if (observedElementsRef.current.has(index)) return\n\n // 创建 ResizeObserver(懒加载)\n if (!observerRef.current) {\n observerRef.current = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n const idx = Number(entry.target.getAttribute('data-index'))\n if (isNaN(idx)) return\n\n const size = isHorizontal\n ? entry.contentRect.width\n : entry.contentRect.height\n\n onResize(idx, size)\n })\n })\n }\n\n // 设置 data-index 属性\n element.setAttribute('data-index', String(index))\n\n // 开始观察\n observerRef.current.observe(element)\n observedElementsRef.current.set(index, element)\n }, [enabled, isHorizontal, onResize])\n\n /**\n * 小程序实现:使用 IntersectionObserver + SelectorQuery\n * 使用唯一 id 选择器,避免多 List 并存时误命中(index>=0 为 item,index<0 为 header)\n * 使用 Taro.nextTick 延后 observe,确保 setData 已提交、节点已挂载,避免 \"Node is not found\" 报错\n */\n const observeMiniProgram = useCallback((_element: any, index: number) => {\n if (!enabled) return\n\n // 避免重复观察\n if (intersectionObserversRef.current.has(index)) return\n\n const selector = index >= 0\n ? `#${listId}-list-item-inner-${index}`\n : `#${listId}-list-header-inner-${-index - 1}`\n\n const doObserve = () => {\n try {\n const observerScope = getIntersectionObserverScopeForRef(listViewportRef)\n const observer = Taro.createIntersectionObserver(observerScope, {\n observeAll: true\n })\n\n // 参照视口:仍为 `#${listId}` 字符串;与 `listViewportRef` 无 API 耦合,后者只影响上面 `createIntersectionObserver` 的首参\n observer.relativeTo(`#${listId}`)\n\n // 观察元素进入可见区域(唯一 id 避免跨 List 误命中)\n observer.observe(selector, (res) => {\n if (res.intersectionRatio > 0) {\n // 与 observe 目标同一节点,SelectorQuery 的 in(scope) 与该节点 _scope 一致\n createSelectorQueryForRef({ current: _element } as RefObject<any>)\n .select(selector)\n .boundingClientRect((rect: any) => {\n if (rect) {\n const size = isHorizontal ? rect.width : rect.height\n onResize(index, size)\n }\n })\n .exec()\n }\n })\n\n intersectionObserversRef.current.set(index, observer)\n } catch {\n // ignore observe failure\n }\n }\n\n Taro.nextTick(doObserve)\n }, [enabled, isHorizontal, listId, listViewportRef, onResize])\n\n /**\n * 观察元素(平台自动适配)\n */\n const observe = useCallback((element: HTMLElement | null, index: number) => {\n if (!enabled) return\n\n if (isH5) {\n observeH5(element, index)\n } else if (isMiniProgram) {\n observeMiniProgram(element, index)\n }\n }, [enabled, observeH5, observeMiniProgram])\n\n /**\n * 取消观察元素\n */\n const unobserve = useCallback((element: HTMLElement | null) => {\n if (!element) return\n\n const index = Number(element.getAttribute('data-index'))\n if (isNaN(index)) return\n\n if (isH5 && observerRef.current) {\n observerRef.current.unobserve(element)\n observedElementsRef.current.delete(index)\n } else if (isMiniProgram) {\n const observer = intersectionObserversRef.current.get(index)\n if (observer) {\n observer.disconnect()\n intersectionObserversRef.current.delete(index)\n }\n }\n }, [])\n\n /**\n * 断开所有观察\n */\n const disconnect = useCallback(() => {\n if (isH5 && observerRef.current) {\n observerRef.current.disconnect()\n observerRef.current = null\n observedElementsRef.current.clear()\n } else if (isMiniProgram) {\n intersectionObserversRef.current.forEach((observer) => {\n observer.disconnect()\n })\n intersectionObserversRef.current.clear()\n }\n }, [])\n\n /**\n * 组件卸载时清理\n */\n useEffect(() => {\n return () => {\n disconnect()\n }\n }, [disconnect])\n\n return {\n observe,\n unobserve,\n disconnect\n }\n}\n"],"names":[],"mappings":";;;;AA0CM,SAAU,iBAAiB,CAC/B,OAAiC,EAAA;AAEjC,IAAA,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,OAAO;;AAG5E,IAAA,MAAM,WAAW,GAAG,MAAM,CAAwB,IAAI,CAAC;;IAGvD,MAAM,wBAAwB,GAAG,MAAM,CAAyC,IAAI,GAAG,EAAE,CAAC;;IAG1F,MAAM,mBAAmB,GAAG,MAAM,CAAkC,IAAI,GAAG,EAAE,CAAC;AAE9E;;AAEG;IACH,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,OAA2B,EAAE,KAAa,KAAI;AAC3E,QAAA,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO;YAAE;;AAG1B,QAAA,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE;;AAG5C,QAAA,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;YACxB,WAAW,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,CAAC,OAAO,KAAI;AACnD,gBAAA,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,KAAI;AACxB,oBAAA,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;oBAC3D,IAAI,KAAK,CAAC,GAAG,CAAC;wBAAE;oBAEhB,MAAM,IAAI,GAAG;AACX,0BAAE,KAAK,CAAC,WAAW,CAAC;AACpB,0BAAE,KAAK,CAAC,WAAW,CAAC,MAAM;AAE5B,oBAAA,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;AACrB,iBAAC,CAAC;AACJ,aAAC,CAAC;;;QAIJ,OAAO,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;AAGjD,QAAA,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACpC,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC;KAChD,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;AAErC;;;;AAIG;IACH,MAAM,kBAAkB,GAAG,WAAW,CAAC,CAAC,QAAa,EAAE,KAAa,KAAI;AACtE,QAAA,IAAI,CAAC,OAAO;YAAE;;AAGd,QAAA,IAAI,wBAAwB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE;AAEjD,QAAA,MAAM,QAAQ,GAAG,KAAK,IAAI;AACxB,cAAE,CAAA,CAAA,EAAI,MAAM,CAAA,iBAAA,EAAoB,KAAK,CAAE;cACrC,IAAI,MAAM,CAAA,mBAAA,EAAsB,CAAC,KAAK,GAAG,CAAC,CAAA,CAAE;QAEhD,MAAM,SAAS,GAAG,MAAK;AACrB,YAAA,IAAI;AACF,gBAAA,MAAM,aAAa,GAAG,kCAAkC,CAAC,eAAe,CAAC;AACzE,gBAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,0BAA0B,CAAC,aAAa,EAAE;AAC9D,oBAAA,UAAU,EAAE;AACb,iBAAA,CAAC;;AAGF,gBAAA,QAAQ,CAAC,UAAU,CAAC,IAAI,MAAM,CAAA,CAAE,CAAC;;gBAGjC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,KAAI;AACjC,oBAAA,IAAI,GAAG,CAAC,iBAAiB,GAAG,CAAC,EAAE;;AAE7B,wBAAA,yBAAyB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAoB;6BAC9D,MAAM,CAAC,QAAQ;AACf,6BAAA,kBAAkB,CAAC,CAAC,IAAS,KAAI;4BAChC,IAAI,IAAI,EAAE;AACR,gCAAA,MAAM,IAAI,GAAG,YAAY,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM;AACpD,gCAAA,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;;AAEzB,yBAAC;AACA,6BAAA,IAAI,EAAE;;AAEb,iBAAC,CAAC;gBAEF,wBAAwB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC;;AACrD,YAAA,OAAA,EAAA,EAAM;;;AAGV,SAAC;AAED,QAAA,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;AAC1B,KAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;AAE9D;;AAEG;IACH,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,OAA2B,EAAE,KAAa,KAAI;AACzE,QAAA,IAAI,CAAC,OAAO;YAAE;QAEd,IAAI,IAAI,EAAE;AACR,YAAA,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC;;aACpB,IAAI,aAAa,EAAE;AACxB,YAAA,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC;;KAErC,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAE5C;;AAEG;AACH,IAAA,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,OAA2B,KAAI;AAC5D,QAAA,IAAI,CAAC,OAAO;YAAE;QAEd,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACxD,IAAI,KAAK,CAAC,KAAK,CAAC;YAAE;AAElB,QAAA,IAAI,IAAI,IAAI,WAAW,CAAC,OAAO,EAAE;AAC/B,YAAA,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;AACtC,YAAA,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;;aACpC,IAAI,aAAa,EAAE;YACxB,MAAM,QAAQ,GAAG,wBAAwB,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAC5D,IAAI,QAAQ,EAAE;gBACZ,QAAQ,CAAC,UAAU,EAAE;AACrB,gBAAA,wBAAwB,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;;;KAGnD,EAAE,EAAE,CAAC;AAEN;;AAEG;AACH,IAAA,MAAM,UAAU,GAAG,WAAW,CAAC,MAAK;AAClC,QAAA,IAAI,IAAI,IAAI,WAAW,CAAC,OAAO,EAAE;AAC/B,YAAA,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE;AAChC,YAAA,WAAW,CAAC,OAAO,GAAG,IAAI;AAC1B,YAAA,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE;;aAC9B,IAAI,aAAa,EAAE;YACxB,wBAAwB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAI;gBACpD,QAAQ,CAAC,UAAU,EAAE;AACvB,aAAC,CAAC;AACF,YAAA,wBAAwB,CAAC,OAAO,CAAC,KAAK,EAAE;;KAE3C,EAAE,EAAE,CAAC;AAEN;;AAEG;IACH,SAAS,CAAC,MAAK;AACb,QAAA,OAAO,MAAK;AACV,YAAA,UAAU,EAAE;AACd,SAAC;AACH,KAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAEhB,OAAO;QACL,OAAO;QACP,SAAS;QACT;KACD;AACH;;;;"}
|
|
@@ -77,8 +77,6 @@ export interface ListProps {
|
|
|
77
77
|
scrollElement?: React.RefObject<HTMLElement | null>;
|
|
78
78
|
/** 向外透出滚动容器,供子 List 作 scrollElement */
|
|
79
79
|
scrollRef?: React.MutableRefObject<HTMLElement | null>;
|
|
80
|
-
/** 仅小程序:SelectorQuery / IO 作用域(如自定义组件内传 `this`),未传则沿用 page */
|
|
81
|
-
selectorQueryScope?: object;
|
|
82
80
|
}
|
|
83
81
|
export interface ListHandle {
|
|
84
82
|
scroll: (options?: {
|
|
@@ -15,7 +15,7 @@ import { ListItem } from './ListItem.js';
|
|
|
15
15
|
import { NoMore } from './NoMore.js';
|
|
16
16
|
import { StickyHeader } from './StickyHeader.js';
|
|
17
17
|
import { StickySection } from './StickySection.js';
|
|
18
|
-
import { isWeapp,
|
|
18
|
+
import { isWeapp, createSelectorQueryForRef, isH5, supportsNativeRefresher } from './utils.js';
|
|
19
19
|
import { getScrollViewContextNode } from '../../utils/dom.js';
|
|
20
20
|
|
|
21
21
|
function accumulate(arr) {
|
|
@@ -69,7 +69,7 @@ const InnerList = (props, ref) => {
|
|
|
69
69
|
const { stickyHeader = false, space = 0, height = 400, width = '100%', showScrollbar = true, scrollTop: controlledScrollTop, scrollX = false, scrollY = true, onScroll, onScrollToUpper, onScrollToLower, onScrollStart, onScrollEnd, upperThreshold = 50, lowerThreshold = 50, cacheCount = 2, cacheExtent, enableBackToTop, className, style, children, nestedScroll, scrollElement, scrollRef: scrollRefProp, } = props;
|
|
70
70
|
const isHorizontal = scrollX === true;
|
|
71
71
|
const listType = nestedScroll === true ? 'nested' : 'default';
|
|
72
|
-
const { effectiveScrollElement, effectiveStartOffset, effectiveStartOffsetRef, useScrollElementMode, needAutoFind, autoFindStatus, contentWrapperRef, contentId, } = useListNestedScroll(listType, scrollElement, undefined, isHorizontal
|
|
72
|
+
const { effectiveScrollElement, effectiveStartOffset, effectiveStartOffsetRef, useScrollElementMode, needAutoFind, autoFindStatus, contentWrapperRef, contentId, } = useListNestedScroll(listType, scrollElement, undefined, isHorizontal);
|
|
73
73
|
const DEFAULT_ITEM_WIDTH = 120;
|
|
74
74
|
const DEFAULT_ITEM_HEIGHT = 40;
|
|
75
75
|
const defaultItemSize = isHorizontal ? DEFAULT_ITEM_WIDTH : DEFAULT_ITEM_HEIGHT;
|
|
@@ -125,7 +125,7 @@ const InnerList = (props, ref) => {
|
|
|
125
125
|
if (!isWeapp)
|
|
126
126
|
return;
|
|
127
127
|
Taro.nextTick(() => {
|
|
128
|
-
|
|
128
|
+
createSelectorQueryForRef(containerRef)
|
|
129
129
|
.select(`#${listId}`)
|
|
130
130
|
.boundingClientRect((rect) => {
|
|
131
131
|
const measured = isHorizontal ? rect === null || rect === void 0 ? void 0 : rect.width : rect === null || rect === void 0 ? void 0 : rect.height;
|
|
@@ -450,7 +450,7 @@ const InnerList = (props, ref) => {
|
|
|
450
450
|
enabled: props.useResizeObserver === true,
|
|
451
451
|
isHorizontal,
|
|
452
452
|
listId,
|
|
453
|
-
|
|
453
|
+
listViewportRef: containerRef,
|
|
454
454
|
onResize: (index, size) => {
|
|
455
455
|
var _a;
|
|
456
456
|
const oldSize = sizeCache.getItemSize(index);
|
|
@@ -889,7 +889,7 @@ const InnerList = (props, ref) => {
|
|
|
889
889
|
listContentLength: listContentLengthRef.current,
|
|
890
890
|
};
|
|
891
891
|
useListScrollElementAttach(useScrollElementMode && isH5, effectiveScrollElement, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, scrollAttachRefsRef);
|
|
892
|
-
useListScrollElementAttachWeapp(useScrollElementMode && isWeapp, effectiveScrollElement, effectiveStartOffsetRef, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, scrollAttachRefsRef, initialContainerLength
|
|
892
|
+
useListScrollElementAttachWeapp(useScrollElementMode && isWeapp, effectiveScrollElement, effectiveStartOffsetRef, effectiveStartOffset, isHorizontal, setContainerLength, updateRenderOffset, scrollRefProp, scrollAttachRefsRef, initialContainerLength);
|
|
893
893
|
// 吸顶/吸左 header
|
|
894
894
|
const stickyHeaderNode = React.useMemo(() => {
|
|
895
895
|
if (!stickyHeader)
|
|
@@ -971,7 +971,7 @@ const InnerList = (props, ref) => {
|
|
|
971
971
|
Taro.nextTick(() => {
|
|
972
972
|
if (!headerRefsRef.current.has(sectionIndex))
|
|
973
973
|
return;
|
|
974
|
-
|
|
974
|
+
createSelectorQueryForRef({ current: el })
|
|
975
975
|
.select(`#${listId}-list-header-inner-${sectionIndex}`)
|
|
976
976
|
.boundingClientRect((rect) => {
|
|
977
977
|
if (rect) {
|
|
@@ -1117,7 +1117,7 @@ const InnerList = (props, ref) => {
|
|
|
1117
1117
|
Taro.nextTick(() => {
|
|
1118
1118
|
if (!itemRefsRef.current.has(capturedIndex))
|
|
1119
1119
|
return;
|
|
1120
|
-
|
|
1120
|
+
createSelectorQueryForRef({ current: el })
|
|
1121
1121
|
// 页面上可能同时存在多个 List,inner id 必须带 listId 前缀避免跨列表误命中
|
|
1122
1122
|
.select(`#${listId}-list-item-inner-${capturedIndex}`)
|
|
1123
1123
|
.boundingClientRect((rect) => {
|