如何在样式组件中获取当前 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/