From 5ce127e383e52d7d160c85661c706e69953e5ae9 Mon Sep 17 00:00:00 2001 From: huangchen1031 Date: Mon, 12 Aug 2024 11:17:34 +0800 Subject: [PATCH] fix(virtualScoll): fix visibleData calculation to fix blank bug (#2999) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(usevirtualscoll): 修改visibleData计算方式,解决可视区域过高时,滚动后底部留白的问题 fix #2956 * chore: update snapshot * fix: lastIndex初始值设置问题 --------- Co-authored-by: Uyarn --- src/hooks/useVirtualScroll.ts | 44 +- test/snap/__snapshots__/csr.test.jsx.snap | 3268 ++------------------- 2 files changed, 219 insertions(+), 3093 deletions(-) diff --git a/src/hooks/useVirtualScroll.ts b/src/hooks/useVirtualScroll.ts index b219ea58a..144a9148d 100644 --- a/src/hooks/useVirtualScroll.ts +++ b/src/hooks/useVirtualScroll.ts @@ -27,7 +27,7 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV const [trHeightList, setTrHeightList] = useState([]); const containerWidth = useRef(0); const containerHeight = useRef(0); - const [startAndEndIndex, setStartAndEndIndex] = useState<[number, number]>([0, 15]); + const [startAndEndIndex, setStartAndEndIndex] = useState<[number, number]>([0, (scroll?.bufferSize || 10) * 3]); // 设置初始值 const tScroll = useMemo(() => { @@ -43,17 +43,17 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV // 当前场景是否满足开启虚拟滚动的条件 const isVirtualScroll = useMemo(() => tScroll.type === 'virtual' && tScroll.threshold < data.length, [tScroll, data]); - const getTrScrollTopHeightList = (trHeightList: number[], containerHeight: number) => { + const getTrScrollTopHeightList = (trHeightList: number[]) => { const list: number[] = []; // 大数据场景不建议使用 forEach 一类函数迭代 - // 当前行滚动高度 = 上一行滚动高度 + 当前行高度 + 容器高度 + // 当前行滚动高度 = 上一行滚动高度 + 当前行高度 for (let i = 0, len = data.length; i < len; i++) { - list[i] = (list[i - 1] || containerHeight) + (trHeightList[i] || tScroll.rowHeight); + list[i] = (list[i - 1] || 0) + (trHeightList[i] || tScroll.rowHeight); } return list; }; - const tripleBufferSize = useMemo(() => tScroll.bufferSize * 3, [tScroll.bufferSize]); + // const tripleBufferSize = useMemo(() => tScroll.bufferSize * 3, [tScroll.bufferSize]); const updateVisibleData = (trScrollTopHeightList: number[], scrollTop: number) => { let currentIndex = -1; @@ -64,14 +64,24 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV break; } } + let lastIndex = trScrollTopHeightList.length; + const containerCurrentHeight = containerHeight.current || container.current.getBoundingClientRect().height; + const scrollBottom = scrollTop + containerCurrentHeight; + // 获取当前视窗的最后一个元素(大数据场景不建议使用 forEach 一类函数迭代) + for (let i = currentIndex, len = trScrollTopHeightList.length; i < len; i++) { + if (trScrollTopHeightList[i] >= scrollBottom) { + lastIndex = i; + break; + } + } if (currentIndex < 0) return; - const startIndex = Math.min(currentIndex, trScrollTopHeightList.length - tripleBufferSize); - const endIndex = startIndex + tripleBufferSize; + const startIndex = Math.max(currentIndex - tScroll.bufferSize, 0); + const endIndex = Math.min(lastIndex + tScroll.bufferSize, trScrollTopHeightList.length); if (startAndEndIndex.join() !== [startIndex, endIndex].join() && startIndex >= 0) { const tmpVisibleData = data.slice(startIndex, endIndex); setVisibleData(tmpVisibleData); const lastScrollTop = trScrollTopHeightList[startIndex - 1]; - const top = lastScrollTop > 0 ? lastScrollTop - containerHeight.current : 0; + const top = lastScrollTop > 0 ? lastScrollTop : 0; setTranslateY(top); setStartAndEndIndex([startIndex, endIndex]); } @@ -88,7 +98,7 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV newTrHeightList[rowIndex] = trHeight; setTrHeightList(newTrHeightList); - const scrollTopHeightList = getTrScrollTopHeightList(newTrHeightList, containerHeight.current); + const scrollTopHeightList = getTrScrollTopHeightList(newTrHeightList); trScrollTopHeightList.current = scrollTopHeightList; const lastIndex = scrollTopHeightList.length - 1; @@ -123,8 +133,7 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV }; const updateScrollTop = ({ index, top = 0, behavior }: ScrollToElementParams) => { - const containerCurrentHeight = containerHeight.current || container.current.getBoundingClientRect().height; - const scrollTop = trScrollTopHeightList.current[index] - containerCurrentHeight - top; + const scrollTop = trScrollTopHeightList.current[index] - top; container.current?.scrollTo({ top: scrollTop, behavior: behavior || 'auto', @@ -153,18 +162,15 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV useEffect( () => { if (!isVirtualScroll) { - trScrollTopHeightList.current = getTrScrollTopHeightList( - trHeightList, - container.current?.getBoundingClientRect().height, - ); + trScrollTopHeightList.current = getTrScrollTopHeightList(trHeightList); return; } // 给数据添加下标 addIndexToData(data); setScrollHeight(data.length * tScroll.rowHeight); - const startIndex = startAndEndIndex[0]; - const tmpData = data.slice(startIndex, startIndex + tripleBufferSize); + const [startIndex, endIndex] = startAndEndIndex; + const tmpData = data.slice(startIndex, endIndex); setVisibleData(tmpData); @@ -172,14 +178,14 @@ const useVirtualScroll = (container: MutableRefObject, params: UseV if (container.current) { const tmpContainerHeight = container.current.getBoundingClientRect().height; containerHeight.current = tmpContainerHeight; - const scrollTopHeightList = getTrScrollTopHeightList(trHeightList, tmpContainerHeight); + const scrollTopHeightList = getTrScrollTopHeightList(trHeightList); trScrollTopHeightList.current = scrollTopHeightList; clearTimeout(timer); } }, 1); }, // eslint-disable-next-line - [container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList, tripleBufferSize], + [container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList], ); return { diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index 758173fb7..28a97d654 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -112526,2960 +112526,188 @@ exports[`csr snapshot test > csr test src/table/_example/tree-select.tsx 1`] = ` algolia 服务报销 - - - - - - - - - 11 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - 相关周边制作费 - - - - - - - - - - - 12 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - 激励奖品快递费 - - - - - - - - - - - 13 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - 宣传物料制作费用 - - - - - - - - - - - 14 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - algolia 服务报销 - - - - - - - - - - - 15 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - 相关周边制作费 - - - - - - - - - - - 16 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - 激励奖品快递费 - - - - - - - - - - - 17 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - 宣传物料制作费用 - - - - - - - - - - - 18 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - algolia 服务报销 - - - - - - - - - - - 19 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - 相关周边制作费 - - - - - - - - - - - 20 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - 激励奖品快递费 - - - - - - - - - - - 21 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - 宣传物料制作费用 - - - - - - - - - - - 22 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - algolia 服务报销 - - - - - - - - - - - 23 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - 相关周边制作费 - - - - - - - - - - - 24 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - 激励奖品快递费 - - - - - - - - - - - 25 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - 宣传物料制作费用 - - - - - - - - - - - 26 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - algolia 服务报销 - - - - - - - - - - - 27 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - 相关周边制作费 - - - - - - - - - - - 28 - - -
- - - - - - 贾明 -
- - -
- - - - - 审批通过 - -
- - - 激励奖品快递费 - - - - - - - - - - - 29 - - -
- - - - - - 张三 -
- - -
- - - - - 审批失败 - -
- - - 宣传物料制作费用 - - - - - - - - - - - 30 - - -
- - - - - - 王芳 -
- - -
- - - - - 审批过期 - -
- - - algolia 服务报销 - - - - - - - - - -`; - -exports[`csr snapshot test > csr test src/table/_example/virtual-scroll.tsx 1`] = ` -
-
-
-
-
- -
-
- -
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- 序号 -
-
-
- 申请人 -
-
-
- 申请状态 -
-
-
- 申请事项 -
-
-
- 邮箱地址 -
-
-
- 申请时间 -
-
- 1 - - 贾明 - -
- - - - - 审批通过 - -
-
- 部分宣传物料制作费用 - - w.cezkdudy@lhll.au - - 2022-01-01 -
- 2 - - 张三 - -
- - - - - 审批失败 - -
-
- algolia 服务报销 - - r.nmgw@peurezgn.sl - - 2022-02-01 -
- 3 - - 王芳 - -
- - - - - 审批过期 - -
-
- 相关周边制作费 - - p.cumx@rampblpa.ru - - 2022-03-01 -
- 4 - - 贾明 - -
- - - - - 审批通过 - -
-
- 激励奖品快递费 - - w.cezkdudy@lhll.au - - 2022-04-01 -
- 5 - - 张三 - -
- - - - - 审批失败 - -
-
- 部分宣传物料制作费用 - - r.nmgw@peurezgn.sl - - 2022-01-01 -
- 6 - - 王芳 - -
- - - - - 审批过期 - -
-
- algolia 服务报销 - - p.cumx@rampblpa.ru - - 2022-02-01 -
- 7 - - 贾明 - -
- - - - - 审批通过 - -
-
- 相关周边制作费 - - w.cezkdudy@lhll.au - - 2022-03-01 -
- 8 - - 张三 - -
- - - - - 审批失败 - -
-
- 激励奖品快递费 - - r.nmgw@peurezgn.sl - - 2022-04-01 -
- 9 - - 王芳 - -
- - - - - 审批过期 - -
-
- 部分宣传物料制作费用 - - p.cumx@rampblpa.ru - - 2022-01-01 -
- 10 - - 贾明 - -
- - - - - 审批通过 - -
-
- algolia 服务报销 - - w.cezkdudy@lhll.au - - 2022-02-01 -
- 11 - - 贾明 - -
- - - - - 审批失败 - -
-
- 部分宣传物料制作费用 - - w.cezkdudy@lhll.au - - 2022-01-01 -
- 12 - - 张三 - -
- - - - - 审批过期 - -
-
- algolia 服务报销 - - r.nmgw@peurezgn.sl - - 2022-02-01 -
- 13 - - 王芳 - -
- - - - - 审批通过 - -
-
- 相关周边制作费 - - p.cumx@rampblpa.ru - - 2022-03-01 -
- 14 - - 贾明 - -
- - - - - 审批失败 - -
-
- 激励奖品快递费 - - w.cezkdudy@lhll.au - - 2022-04-01 -
- 15 - - 张三 - +
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/table/_example/virtual-scroll.tsx 1`] = ` +
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] csr test src/table/_example/virtual-scroll.tsx 1`] - - - - - - - - - - - - - - - -
- - - - - 审批过期 - + 序号
- -
- 部分宣传物料制作费用 - - r.nmgw@peurezgn.sl - - 2022-01-01 -
- 16 - - 王芳 - +
- - - - - 审批通过 - + 申请人
- -
- algolia 服务报销 - - p.cumx@rampblpa.ru - - 2022-02-01 -
- 17 - - 贾明 - +
- - - - - 审批失败 - + 申请状态
- -
- 相关周边制作费 - - w.cezkdudy@lhll.au - - 2022-03-01 -
- 18 - - 张三 - +
- - - - - 审批过期 - + 申请事项
- -
- 激励奖品快递费 - + - r.nmgw@peurezgn.sl - - + 邮箱地址 + + + - 2022-04-01 - +
+ 申请时间 +
+
- 19 + 1 - 王芳 + 贾明 csr test src/table/_example/virtual-scroll.tsx 1`] - p.cumx@rampblpa.ru + w.cezkdudy@lhll.au csr test src/table/_example/virtual-scroll.tsx 1`] - 20 + 2 - 贾明 + 张三 csr test src/table/_example/virtual-scroll.tsx 1`] - w.cezkdudy@lhll.au + r.nmgw@peurezgn.sl csr test src/table/_example/virtual-scroll.tsx 1`] - 21 + 3 - 贾明 + 王芳 csr test src/table/_example/virtual-scroll.tsx 1`] - 部分宣传物料制作费用 + 相关周边制作费 - w.cezkdudy@lhll.au + p.cumx@rampblpa.ru - 2022-01-01 + 2022-03-01
- 22 + 4 - 张三 + 贾明 csr test src/table/_example/virtual-scroll.tsx 1`] - algolia 服务报销 + 激励奖品快递费 - r.nmgw@peurezgn.sl + w.cezkdudy@lhll.au - 2022-02-01 + 2022-04-01
- 23 + 5 - 王芳 + 张三 csr test src/table/_example/virtual-scroll.tsx 1`] - 相关周边制作费 + 部分宣传物料制作费用 - p.cumx@rampblpa.ru + r.nmgw@peurezgn.sl - 2022-03-01 + 2022-01-01
- 24 + 6 - 贾明 + 王芳 csr test src/table/_example/virtual-scroll.tsx 1`] - 激励奖品快递费 + algolia 服务报销 - w.cezkdudy@lhll.au + p.cumx@rampblpa.ru - 2022-04-01 + 2022-02-01
- 25 + 7 - 张三 + 贾明 csr test src/table/_example/virtual-scroll.tsx 1`] - 部分宣传物料制作费用 + 相关周边制作费 - r.nmgw@peurezgn.sl + w.cezkdudy@lhll.au - 2022-01-01 + 2022-03-01
- 26 + 8 - 王芳 + 张三 csr test src/table/_example/virtual-scroll.tsx 1`] - algolia 服务报销 + 激励奖品快递费 - p.cumx@rampblpa.ru + r.nmgw@peurezgn.sl - 2022-02-01 + 2022-04-01
- 27 + 9 - 贾明 + 王芳 csr test src/table/_example/virtual-scroll.tsx 1`] - 相关周边制作费 + 部分宣传物料制作费用 - w.cezkdudy@lhll.au + p.cumx@rampblpa.ru - 2022-03-01 + 2022-01-01
- 28 + 10 - 张三 + 贾明 csr test src/table/_example/virtual-scroll.tsx 1`] - 激励奖品快递费 - - r.nmgw@peurezgn.sl - - 2022-04-01 -
- 29 - - 王芳 - -
- - - - - 审批失败 - -
-
- 部分宣传物料制作费用 - - p.cumx@rampblpa.ru - - 2022-01-01 -
- 30 - - 贾明 - -
- - - - - 审批过期 - -
-