press-pix
Version:
基于 PixUI 的 Press 组件库
82 lines (61 loc) • 1.9 kB
text/typescript
import { useEffect, useRef, useCallback } from 'preact/hooks';
export const useLoadMore = (onReachBottom, options: {
threshold?: number;
debounceDelay?: number;
isEnabled?: boolean;
finished?: boolean;
containerRef?: any;
} = {}) => {
const {
threshold = 100,
debounceDelay = 100,
isEnabled = true,
finished,
containerRef: externalContainerRef, // 外部传入的容器ref
} = options;
const internalContainerRef = useRef(null);
const containerRef = externalContainerRef || internalContainerRef;
// 防抖函数
const debounce = useCallback((func, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}, []);
// 触底判断
const checkIsBottom = useCallback((element) => {
if (!element) return false;
const { scrollTop, scrollHeight, clientHeight } = element;
const scrollBottom = scrollHeight - scrollTop - clientHeight;
return scrollBottom <= threshold;
}, [threshold]);
// 滚动处理
const handleScroll = useCallback(
debounce(() => {
if (!isEnabled || finished) return; // finished时不再触发
const container = containerRef.current;
if (!container) return;
if (checkIsBottom(container)) {
onReachBottom();
}
}, debounceDelay),
[finished, debounceDelay, isEnabled, checkIsBottom, onReachBottom],
);
// 事件监听
useEffect(() => {
const container = containerRef.current;
if (!container) return;
if (!isEnabled) {
container.removeEventListener('scroll', handleScroll);
return;
}
container.addEventListener('scroll', handleScroll);
return () => {
container.removeEventListener('scroll', handleScroll);
};
}, [handleScroll, isEnabled, containerRef]);
return {
containerRef,
};
};