如何在样式组件中获取当前 window pageYOffset?
How to get current window pageYOffset in styled component?
我正在努力处理依赖于 window 的 scrollYOffset 的翻译动画。
我有这样的东西:
const StyledHeading = styled.h1`
font-size: ${({ theme }) => theme.fontSize.l};
letter-spacing: 1px;
font-family: ${({ theme }) => theme.font.firaSans};
margin: 0;
transition: 0.25s ease-in-out;
transform: translateX(${({ offset }) => (offset > 100 ? '-50px' : '0px')});
`;
export default function Navbar() {
const [offset, setOffset] = useState(window.pageYOffset);
useEffect(() => {
window.addEventListener('scroll', () => {
setOffset(window.pageYOffset);
});
});
return (
<StyledHeader >
<StyledWrapper>
<StyledHeading offset={offset}>
Bookphiles <i className="fas fa-book-open" />
</StyledHeading>
<nav>
<NavLinks />
</nav>
</StyledWrapper>
</StyledHeader>
);
}
但它似乎以非常低效的方式完成,因为每次滚动都会导致 DOM 重新渲染。可以用更好的方式完成吗?
恕我直言,如果你想避免断断续续的动画,你应该依靠 refs DOM 管理而不是 React render():
import React, { useState, useEffect, createRef } from 'react';
export default function Navbar() {
const ref = createRef();
useEffect(() => {
window.addEventListener('scroll', handleScroll);
});
handleScroll = (e) => {
const offset = window.pageYOffset;
ref.current.style.transform = `translateX(${({ offset }) => (offset > 100 ? '-50px' : '0px')})`;
}
return (
//...code
<StyledHeading ref={ref}>
Bookphiles <i className="fas fa-book-open" />
</StyledHeading>
//..code
);
}
请注意,我的代码中可能有一些拼写错误,但概念是不涉及 re-rendering 滚动管理。
记得在卸载组件之前删除侦听器。
尝试使用 lodash 中的节流或去抖功能来限制事件处理函数的执行次数。这样事件处理程序最多只会每 200 毫秒执行一次:
window.addEventListener('scroll', _.throttle(() => {
setOffset(window.pageYOffset);
}, 200));
这是一篇很好的文章,更详细地解释了这个想法并提供了更多示例:https://css-tricks.com/debouncing-throttling-explained-examples/
我正在努力处理依赖于 window 的 scrollYOffset 的翻译动画。
我有这样的东西:
const StyledHeading = styled.h1`
font-size: ${({ theme }) => theme.fontSize.l};
letter-spacing: 1px;
font-family: ${({ theme }) => theme.font.firaSans};
margin: 0;
transition: 0.25s ease-in-out;
transform: translateX(${({ offset }) => (offset > 100 ? '-50px' : '0px')});
`;
export default function Navbar() {
const [offset, setOffset] = useState(window.pageYOffset);
useEffect(() => {
window.addEventListener('scroll', () => {
setOffset(window.pageYOffset);
});
});
return (
<StyledHeader >
<StyledWrapper>
<StyledHeading offset={offset}>
Bookphiles <i className="fas fa-book-open" />
</StyledHeading>
<nav>
<NavLinks />
</nav>
</StyledWrapper>
</StyledHeader>
);
}
但它似乎以非常低效的方式完成,因为每次滚动都会导致 DOM 重新渲染。可以用更好的方式完成吗?
恕我直言,如果你想避免断断续续的动画,你应该依靠 refs DOM 管理而不是 React render():
import React, { useState, useEffect, createRef } from 'react';
export default function Navbar() {
const ref = createRef();
useEffect(() => {
window.addEventListener('scroll', handleScroll);
});
handleScroll = (e) => {
const offset = window.pageYOffset;
ref.current.style.transform = `translateX(${({ offset }) => (offset > 100 ? '-50px' : '0px')})`;
}
return (
//...code
<StyledHeading ref={ref}>
Bookphiles <i className="fas fa-book-open" />
</StyledHeading>
//..code
);
}
请注意,我的代码中可能有一些拼写错误,但概念是不涉及 re-rendering 滚动管理。 记得在卸载组件之前删除侦听器。
尝试使用 lodash 中的节流或去抖功能来限制事件处理函数的执行次数。这样事件处理程序最多只会每 200 毫秒执行一次:
window.addEventListener('scroll', _.throttle(() => {
setOffset(window.pageYOffset);
}, 200));
这是一篇很好的文章,更详细地解释了这个想法并提供了更多示例:https://css-tricks.com/debouncing-throttling-explained-examples/