监听向上/向下滚动?

20

我正在开发一个应用程序(ES6),我想知道捕获向上/向下滚动事件的“正确”方法是什么?

我尝试了使用npm安装react-scroll-listener,但是无法在我的ES6类中使其正常工作。

基本上,如果滚动向上,则执行某些操作;如果滚动向下,则执行其他操作。

import React from 'react';
import config from '../config';
import StaticImageList from '../Common/StaticImageList';
import ScrollListener from 'react-scroll-listener';

class Album extends React.Component {
    constructor(props){
      super(props);

    }
    myScrollStartHandler(){
        console.log('Scroll start');

    }
    myScrollEndHandler(){
        console.log('Scroll end 300ms(default)');
    }
    componentDidMount(){
      scrollListener.addScrollHandler('body', myScrollStartHandler, myScrollEndHandler );
    }
    render(){
      return <StaticImageList />;
    }
};

export default Album; 
2个回答

23

这是钩入任何监听器的通用建议:

componentDidMount中附加内容,在componentWillUnmount中取消附加

class Whatever extends Component {
  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll, { passive: true })
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll)
  }

  handleScroll(event) {
    // do something like call `this.setState`
    // access window.scrollY etc
  }
}

谢谢!完美。什么是最好的跨浏览器区分向上滚动和向下滚动的方法? - Kirk Ross
2
只需记录scrollY值并查看下一个值是大于还是小于。 - azium
4
如何在具有"overflow:hidden"属性的元素上捕获鼠标滚轮事件?(即使没有滚动条,仍希望使用鼠标滚轮事件作为触发器) - Kirk Ross
15
不开除我。 - bier hier
几乎完美的答案。如果在addEventListener调用之前添加this.handleScroll = this.handleScroll.bind(this),会更好。没有它,人们将无法调用this.setState,因为this将引用窗口或其他元素,而不是当前组件类。@bierhier这可能是为什么它对你不起作用的原因。 - wviana

15

实际上有很多方法可以做到这一点,但是对于我来说,使用React钩子是最简单的,您只需要:

  • 定义滚动位置的状态
  • 一个函数来更新您的滚动位置状态
  • 在组件挂载时开始滚动监听
  • 在组件卸载时停止监听

像这样:

import React, { useState, useEffect } from 'react';

...
// inside component:

const [scrollPosition, setSrollPosition] = useState(0);
const handleScroll = () => {
    const position = window.pageYOffset;
    setSrollPosition(position);
};

useEffect(() => {
    window.addEventListener('scroll', handleScroll, { passive: true });

    return () => {
        window.removeEventListener('scroll', handleScroll);
    };
}, []);

现在,您有以像素为单位的scrollPosition可供使用

在这种特殊情况下,useEffect将等效于componentDidMount,因为它将在组件挂载后触发,但也会在所有更新后触发,但是 addEventListener 足够聪明,不会启动重复的侦听器。

useEffect中的返回值等同于componentWillUnmount,当组件卸载时,它将被“调用”。


2
addEventListener 会注册多个处理程序,因为每个渲染都有不同的函数。无论如何,它们不会被多次注册,这是因为您已经向 useEffect 提供了一个空的依赖项数组,这实际上将使效果在挂载时运行一次,并在卸载时清理一次。 - Henrik Myntti
谢谢您的解释,那有没有办法在控制台上检查处理程序? - Lucas Andrade
这在Chrome中不起作用。window.pageYOffset将始终返回0。 - Matt West

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