如何描述滚动事件的类型?

23

我在滚动时添加了监听器,并尝试使用事件。如何描述类型而不是任何?

React 16.8.6 Tpescript 3.4

(请注意,我更正了原始文本中的一个拼写错误,并将其从“Tpescript”更改为“TypeScript”)
const Component: FC<IProps> = ({ children, scrollOffset, getScrollTop, videoListScrollUpdate }) => {
    const scroller = useRef<HTMLDivElement>(null)

    useEffect(() => {
        if (scrollOffset && scroller.current) {
            scroller.current.scrollTop = scrollOffset
            return
        }
        if (getScrollTop && scroller.current) {
            scroller.current.addEventListener('scroll', (e: any) => getScrollTop(e.target.scrollTop))
        }
    }, [])

}
5个回答

30
你可以使用(e: React.UIEvent<HTMLElement>)。这是在SyntheticEvents下的UIEvent中描述的。
话虽如此,我建议不要在useEffect中使用useRef。很难确定是否重新调用了useEffect并且scroller.current不为null(即使console.log可能会误导)。
但是我建议改为在您将ref附加到的组件上使用内置的onScroll属性,并给它一个回调来处理滚动。这样,您就不需要在useEffect钩子中手动附加它,在卸载时忘记删除它(会有内存泄漏问题)。
interface IProps {
  children: React.ReactNode;
  getScrollTop: (scrollTop: number) => whatever;
  // Your other Props
}

const ScrollComponent: React.FC<IProps> = ({
  children,
  getScrollTop,
  // Your other props
}): JSX.Element => {
  const handleScroll = (e: React.UIEvent<HTMLElement>): void => {
    e.stopPropagation() // Handy if you want to prevent event bubbling to scrollable parent
    console.log({
      event: e,
      target: e.target, // Note 1* scrollTop is undefined on e.target
      currentTarget: e.currentTarget,
      scrollTop: e.currentTarget.scrollTop,
    });

    const { scrollTop } = e.currentTarget;
    getScrollTop(scrollTop);
  };

  return (
  <div
    // I am assuming you were referencing your scroller as follows.
    // ref={scroller}
    onScroll={handleScroll} // Use the onScroll prop instead.
  >
    {children}
  </div>
  );
};

Note *1: scrollTope.target.scrollTop上不可用,就像您可以在console.log中看到的那样,但在e.currentTarget.scrollTop上可用,因为currentTarget调用附加事件处理程序的元素。


1
谢谢您提供的额外解决方案。这正是我想要实现的,而且比引用更清晰。 - Andres Sepulveda
1
@AndresSepulveda,现在的情况是,你最好使用debounce函数或Intersection ObserverAPI,因为滚动事件触发的次数实在是太多了。 - iamcastelli
1
IntersectionObserver不会立即响应,因此在页面交互方面有时效率高但速度较慢。 - godblessstrawberry
“事件”更适合于滚动处理。Typescript 表示:“类型 'Event' 不能赋值给类型 'UIEvent<HTMLElement>'。” - Vadym P

4

这对我有用 -

//register the scroll event listener callback function
useEffect(() => {
    window.addEventListener('scroll', onScroll)
    return () => {
      window.removeEventListener('scroll', onScroll)
    }
  })

// scroll event callback function
  const onScroll = (e: Event) => {
    const window = e.currentTarget as Window
    //... rest of you function
  }

请确保在tsconfig.json中包含dom lib。
"compilerOptions": {
      "target": "es5",
      "lib": [
        "dom",
        "dom.iterable",
        ...
      ],

3
document.addEventListener("scroll", (event) => {
      const e = event as WheelEvent;
      // do stuff
});

2

const onScroll = (event: UIEvent) => {
      const target = event.target as HTMLElement;

      if (target && target.scrollTop + target.clientHeight + 1 >= target.scrollHeight) {
        // do the magic
      }
    };


0

所以,我只是要扩展@ManjuPrabhu的答案

Header.tsx

const Header: React.FC<IHeader> = () => {
  const [scrolling, setScrolling] = useState(false);

  useEffect(() => {
    window.addEventListener('scroll', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
    };
  });

  const onScroll = (e: Event) => {
    const window = e.currentTarget as Window;
    let currentPosition = window.scrollY;
    currentPosition > 0 ? setScrolling(true) : setScrolling(false);
  };

  return (
    <div
      // clsx is a npm package for conditional classes
      className={clsx('navbar sticky top-0 z-50', { 
        'shadow-2xl': scrolling,
      })}
    >
    Header content
    </div>
  );
};

tsconfig.json

"compilerOptions": {
      "target": "es5",
      "lib": [
        "dom",
        "dom.iterable",
        ...
      ],

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接