在 React 中存储页面偏移值的最佳方式
Best way to store page offset value in React
存储和显示滚动事件改变的页面偏移值的最佳way/recommended模式是什么?
- 将值存储在
useState
中
function App() {
const [posY, setPosY] = useState(0);
useEffect(() => {
const handleScroll = (e) => setPosY(window.pageYOffset);
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{posY}</div>;
}
- 将值存储在
useRef
中
function App() {
const posYRef = useRef(0);
useEffect(() => {
const handleScroll = (e) => {posYRef.current = window.pageYOffset};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{posYRef.current}</div>;
}
- 直接访问并写入 innerHTML(好吧...我是认真的)
function App() {
useEffect(() => {
const handleScroll = (e) => {
document.querySelector("div").innerHTML = window.pageYOffset;
);
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{0}</div>;
}
我知道#1 通常被认为是正确的执行,但我想知道在这种情况下#2 或#3 是否一定是错误的。我们可以实际上 做#2 或#3 因为它们在这种情况下才有效吗?
你应该为此使用状态,因为你想在滚动的基础上显示动画,你应该更新状态,并且状态变化会触发重新渲染。
虽然设置 innerHTML 不会重新呈现。
经过一段时间的额外研究,我得出结论,以上三种方法都可以在特殊情况下使用,尽管 #1 绝对是 standard/recommended 方法。
虽然我同意 state
应该在大多数情况下用于在 React 渲染上获得适当的更新,但 #2 或 #3 也可以工作 如果页面在加载后从未更新。它尤其适用于非 React 支持的第三方库正在操纵 DOMs,并且您需要使用 React 更新它们。它是 React 反模式,可能会造成维护地狱,因此您在执行 #2 或 #3 时应该知道自己在做什么。
关于性能,#2 或#3 理论上应该更快,因为它们都跳过虚拟 DOM 更新。但是,在正常情况下,操作几百个 DOM 个元素时几乎没有区别;这意味着在大多数情况下,使用 #2 或 #3 无法获得更好的渲染性能。
存储和显示滚动事件改变的页面偏移值的最佳way/recommended模式是什么?
- 将值存储在
useState
中
function App() {
const [posY, setPosY] = useState(0);
useEffect(() => {
const handleScroll = (e) => setPosY(window.pageYOffset);
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{posY}</div>;
}
- 将值存储在
useRef
中
function App() {
const posYRef = useRef(0);
useEffect(() => {
const handleScroll = (e) => {posYRef.current = window.pageYOffset};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{posYRef.current}</div>;
}
- 直接访问并写入 innerHTML(好吧...我是认真的)
function App() {
useEffect(() => {
const handleScroll = (e) => {
document.querySelector("div").innerHTML = window.pageYOffset;
);
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
return <div>{0}</div>;
}
我知道#1 通常被认为是正确的执行,但我想知道在这种情况下#2 或#3 是否一定是错误的。我们可以实际上 做#2 或#3 因为它们在这种情况下才有效吗?
你应该为此使用状态,因为你想在滚动的基础上显示动画,你应该更新状态,并且状态变化会触发重新渲染。 虽然设置 innerHTML 不会重新呈现。
经过一段时间的额外研究,我得出结论,以上三种方法都可以在特殊情况下使用,尽管 #1 绝对是 standard/recommended 方法。
虽然我同意 state
应该在大多数情况下用于在 React 渲染上获得适当的更新,但 #2 或 #3 也可以工作 如果页面在加载后从未更新。它尤其适用于非 React 支持的第三方库正在操纵 DOMs,并且您需要使用 React 更新它们。它是 React 反模式,可能会造成维护地狱,因此您在执行 #2 或 #3 时应该知道自己在做什么。
关于性能,#2 或#3 理论上应该更快,因为它们都跳过虚拟 DOM 更新。但是,在正常情况下,操作几百个 DOM 个元素时几乎没有区别;这意味着在大多数情况下,使用 #2 或 #3 无法获得更好的渲染性能。