[英]scrollBy execution in recursive function in ReactJs doesn't work as expected
作為我創建自己的拖放實現過程的一部分,我遇到了拖動項目時自動滾動的問題。 現在我只是嘗試實現原始的自動滾動:當鼠標進入底部觸發區域時,頁面應該開始緩慢滾動,但它滾動了 10px 並停止,而我離開了觸發區域。 這些問題的原因是什么,scrollBy是否會互相重寫直到遞歸結束? 如果是,我該如何避免呢?
代碼示例(高階組件AutoScroll):
export interface IAutoScrollProps {
children: ReactNode;
}
const AutoScroll = ({ children }: IAutoScrollProps) => {
const bottomTriggerClass = `${styles['bottom-trigger']} ${styles['trigger']}
${styles['horizontal']}`;
const overBottomTrigger = useRef(false);
const scrollBottom: () => void | NodeJS.Timeout = useCallback(() => {
window.scrollBy(0, 10);
if (!overBottomTrigger.current) return;
if (document.body.scrollHeight - window.innerHeight - window.scrollY < 20) return;
return setTimeout(scrollBottom, 0);
}, []);
const onBottomTriggerMouseEnter: (e: React.MouseEvent) => void = useCallback(
(e) => {
console.log('enter');
overBottomTrigger.current = true;
scrollBottom();
},[scrollBottom]);
const onBottomTriggerMouseLeave: (e: React.MouseEvent) => void = useCallback((e) => {
console.log('leave');
overBottomTrigger.current = false;
}, []);
return (
<div>
<section className="autoScroll-container p-relative">
{children}
</section>
<span
className={bottomTriggerClass}
onMouseEnter={onBottomTriggerMouseEnter}
onMouseLeave={onBottomTriggerMouseLeave}
></span>
</div>
);
};
export default AutoScroll;
問題可能是由於在您的 scrollBottom() function 中使用了 setTimeout 引起的。setTimeout 是異步的,這意味着它不會立即執行,這意味着您的 scrollBy() 調用可能會相互覆蓋而不會產生預期的效果。
為避免此問題,您應該使用 requestAnimationFrame() 而不是 setTimeout。 這將確保 scrollBy() 調用在同一幀中執行,並應產生所需的自動滾動行為。
試試這個:
const scrollBottom: () => void | NodeJS.Timeout = useCallback(() => {
window.scrollBy(0, 10);
if (!overBottomTrigger.current) return;
if (document.body.scrollHeight - window.innerHeight - window.scrollY < 20) return;
requestAnimationFrame(scrollBottom);
}, []);
這就是我重新創建 scrollBottom function 以使其按預期工作的方式:
const scrollBottom: () => void = useCallback(() => {
if (!overBottomTrigger.current) return;
if (document.body.scrollHeight - window.innerHeight - window.scrollY <= 0)
return;
window.scrollBy(0, 1);
window.onscroll = () => {
scrollBottom();
};
}, []);
我知道,監聽器會創建宏任務,如 setTimeout,但仍不清楚為什么以前的變體不起作用。 scrollBy function 是否累積他們的執行,執行一次?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.