Skip to content

Commit

Permalink
fix(usevirtualscoll): 修改visibleData计算方式,解决可视区域过高时,滚动后底部留白的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
huangchen1031 committed Jul 18, 2024
1 parent 6164b4f commit 28c1254
Showing 1 changed file with 25 additions and 19 deletions.
44 changes: 25 additions & 19 deletions src/hooks/useVirtualScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseV
const [trHeightList, setTrHeightList] = useState<number[]>([]);
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(() => {
Expand All @@ -43,17 +43,17 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, 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;
Expand All @@ -64,14 +64,24 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, params: UseV
break;
}
}
let lastIndex = -1;
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]);
}
Expand All @@ -88,7 +98,7 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, 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;
Expand Down Expand Up @@ -123,8 +133,7 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, 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',
Expand Down Expand Up @@ -153,33 +162,30 @@ const useVirtualScroll = (container: MutableRefObject<HTMLElement>, 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);

const timer = setTimeout(() => {
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 {
Expand Down

0 comments on commit 28c1254

Please sign in to comment.