我在努力依赖于窗口的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重新呈现。可以用更好的方法吗?
答案 0 :(得分:1)
恕我直言,如果您想避免动画不连贯,则应该依靠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
);
}
请注意,我的代码中可能会有一些错别字,但概念是在滚动管理中不涉及重新渲染。 在卸载组件之前,请记住要删除侦听器。
答案 1 :(得分:0)
尝试使用lodash中的节流或防反弹功能来限制事件处理程序功能的执行次数。这样,事件处理程序最多仅每200毫秒执行一次:
window.addEventListener('scroll', _.throttle(() => {
setOffset(window.pageYOffset);
}, 200));
这是一篇很好的文章,它更详细地解释了这个想法并提供了更多示例:https://css-tricks.com/debouncing-throttling-explained-examples/