这是 requestAnimationFrame 的正确使用吗?

问题描述

我正在 React 中试验高性能滚动,并试图真正掌握 requestAnimationFrame,特别是它如何与 React 渲染生命周期相关。

考虑以下代码

function App() {
  const navRef = useRef(null);
  const [width,setWidth] = useState(100);

  useLayoutEffect(() => {
    function adjustWidth(pos) {
      console.log("scrollY is ",pos);
      setWidth(100 - pos);
    }
    function scrollHandler() {
      const pos = window.scrollY;
      requestAnimationFrame(() => {
        adjustWidth(pos);
      });
    }

    document.addEventListener("scroll",scrollHandler);

    return () => {
      document.removeEventListener("scroll",scrollHandler);
    };
  },[]);
  return (
    <div>
      <nav
        ref={navRef}
        style={{ backgroundColor: "red",width: `${width > 0 ? width : 0}%` }}
      ></nav>
      <main style={{ height: "200vh" }}></main>
    </div>
  );
}

首先,我知道通过动画宽度我打破了动画的“规则”之一,因为最好坚持动画不透明度或变换(我可能能够将其切换为 3dtransform 或类似的东西) 但这个演示只是为了我自己的理解。

据我所知,这是这里的事件顺序,如果有人能确认我是对的,或者如果我错了指出我错的地方,那就太好了。

  1. 在第一次渲染时,navRef.current 被分配给 DOM 上的 nav 元素。在渲染之后(但由于 useLayoutEffect 同步)一个函数,adjustWidth() 被创建,scrollHandler() 也是如此。 scrollHandler 附加到滚动事件。
  2. 用户滚动时,会发生以下情况。调用滚动处理程序的次数可能比每 16 毫秒多得多。但是,在注册 pos 变量时,通过将其传递给 rAF,对 adjustWidth() 的调用被限制为大约每 16 毫秒(假设 60hz 显示)。
  3. 调用 adjustWidth 时,更新状态变量 width。这会触发重新渲染。

我还有一些问题:

  1. requestAnimationFrame 会叠加对 adjustWidth 的调用并最终将它们全部触发,还是只会节流并只对每一帧调用回调?
  2. 有时,当我看到人们使用 rAF 时,他们会使用 tick 变量来存储 rAF 的返回值,这与他们使用 setInterval 进行节流的方式非常相似。这是必要的吗?在我看来,rAF 会自动进行节流,所以我不确定您为什么要这样做?

很高兴听到任何比我更了解这一点的人,如果只是说“是的,你完全正确地理解了这一切”,或者甚至更好,“不,这完全是错误的”。

>

非常感谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)