Javascript 卸载时删除事件侦听器

Javascript 卸载时删除事件侦听器,javascript,reactjs,Javascript,Reactjs,我的反应中有更高阶的成分,如下所示: export default function (InnerComponent) { class InfiniteScrolling extends React.Component { constructor(props){ super(props); } componentDidMount() { window.addEventListener('s

我的反应中有更高阶的成分,如下所示:

export default function (InnerComponent) {
    class InfiniteScrolling extends React.Component {

        constructor(props){
            super(props);
        }

        componentDidMount() {
            window.addEventListener('scroll', this.onScroll.bind(this), false);
        }

        componentWillUnmount() {
            window.removeEventListener('scroll', this.onScroll.bind(this), false);
        }

        onScroll() {
            if ((window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 50)) {
                const { scrollFunc } = this.props;
                scrollFunc();
            }
        }

        render() {
            return <InnerComponent {...this.props} />;
        }
    }

    InfiniteScrolling.propTypes = {
        scrollFunc: PropTypes.func.isRequired
    };

    return InfiniteScrolling;
}
constructor(props){
    super(props);
    this.onScroll = this.onScroll.bind(this);
}

componentDidMount() {
    window.addEventListener('scroll', this.onScroll, false);
}

componentWillUnmount() {
    window.removeEventListener('scroll', this.onScroll, false);
}
一切似乎都很好,没有任何问题


我觉得它们完全是一样的,但是第二个运行良好,而第一个在控制台中抛出错误,如前所述

.bind
总是创建一个新函数,因此您需要执行以下操作,因此它会添加和删除相同的函数

    constructor(props){
        super(props);
        this.onScroll = this.onScroll.bind(this); //bind function once
    }

    componentDidMount() {
        window.addEventListener('scroll', this.onScroll, false);
    }

    componentWillUnmount() {
        // you need to unbind the same listener that was binded.
        window.removeEventListener('scroll', this.onScroll, false);
    }

或者你可以使用箭头函数来解决。绑定(这个)问题它工作得很好。

我的项目的一个工作版本,带有箭头函数,没有绑定:

componentDidMount = () => {
  window.addEventListener("wheel", this.onScroll, false);
};

componentWillUnmount() {
  window.removeEventListener("wheel", this.onScroll, false);
}

onScroll = (e) => {
  const item = this.refs.myElement;
  if (e.deltaY > 0) item.scrollLeft += 200;
  else item.scrollLeft -= 200;
};

我知道有点晚了,但我只是遇到了这个问题,我想与您分享我的解决方案,期待任何反馈。此解决方案包括
react hooks
。我希望你喜欢

// Declare a static listener.
const eventListeners = useRef();

// now let's create our scroll Handler
const scrollHandler = useCallback(() => {...},[]);

useEffect(() => {
   // Here will be removing the static listener and then updated it for 
   // our new one since the first time will be empty it won't do anything.
    window.removeEventListener('scroll', eventListeners.current, true);

    // Then will set our current scroll handler to our static listener
    eventListeners.current = scrollHandler;

    // Here will be adding the static listener so we can keep the reference
    // and remove it later on
    window.addEventListener('scroll', eventListeners.current, true);
},[scrollHandler]);


天哪,这么简单的错误<代码>绑定创建一个新函数。我的错!我已经使用了arrow函数,但它仍然没有被调用。我认为没有调用componentWillUnmount。@AmitJS94您可以通过设置断点或简单地登录到控制台来轻松检查是否调用了它。至于“我已经使用了箭头函数”,这并不重要,因为所有作为对象的函数都是通过ref进行比较的。只有添加和删除相同的函数才重要。
// Declare a static listener.
const eventListeners = useRef();

// now let's create our scroll Handler
const scrollHandler = useCallback(() => {...},[]);

useEffect(() => {
   // Here will be removing the static listener and then updated it for 
   // our new one since the first time will be empty it won't do anything.
    window.removeEventListener('scroll', eventListeners.current, true);

    // Then will set our current scroll handler to our static listener
    eventListeners.current = scrollHandler;

    // Here will be adding the static listener so we can keep the reference
    // and remove it later on
    window.addEventListener('scroll', eventListeners.current, true);
},[scrollHandler]);