问题描述
我正在 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 或类似的东西) 但这个演示只是为了我自己的理解。
据我所知,这是这里的事件顺序,如果有人能确认我是对的,或者如果我错了指出我错的地方,那就太好了。
- 在第一次渲染时,navRef.current 被分配给 DOM 上的 nav 元素。在渲染之后(但由于 useLayoutEffect 同步)一个函数,adjustWidth() 被创建,scrollHandler() 也是如此。 scrollHandler 附加到滚动事件。
- 当用户滚动时,会发生以下情况。调用滚动处理程序的次数可能比每 16 毫秒多得多。但是,在注册 pos 变量时,通过将其传递给 rAF,对 adjustWidth() 的调用被限制为大约每 16 毫秒(假设 60hz 显示)。
- 调用 adjustWidth 时,更新状态变量
width
。这会触发重新渲染。
我还有一些问题:
- requestAnimationFrame 会叠加对 adjustWidth 的调用并最终将它们全部触发,还是只会节流并只对每一帧调用回调?
- 有时,当我看到人们使用 rAF 时,他们会使用
tick
变量来存储 rAF 的返回值,这与他们使用 setInterval 进行节流的方式非常相似。这是必要的吗?在我看来,rAF 会自动进行节流,所以我不确定您为什么要这样做?
很高兴听到任何比我更了解这一点的人,如果只是说“是的,你完全正确地理解了这一切”,或者甚至更好,“不,这完全是错误的”。
>非常感谢。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)