簡體   English   中英

ReactJs 中遞歸 function 中的 scrollBy 執行沒有按預期工作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM