使用命名函数的window.removeEventListener无法正常工作

12

我正在使用React,以下是我用来实现无限滚动功能的代码。

componentDidMount() {
    // Flag to check if the content has loaded.
    let flag = true;

    function infiniteScroll() {
      let enterpriseWrap = $('.enterprise-blocks');
      let contentHeight = enterpriseWrap.offsetHeight;
      let yOffset = window.pageYOffset;
      let y = yOffset + window.innerHeight;

      console.log('hey');

      if(this.props.hasMore) {

        if(y >= contentHeight && flag) {
          flag = false;

          this.props.loadMoreVendors(function() {
            flag = true;
          });

        }

      } else {
        window.removeEventListener('scroll', infiniteScroll.bind(this));
      }
    }

    window.addEventListener('scroll', infiniteScroll.bind(this));
  }

我实际上想在所有项目加载完成后解除滚动事件,但是removeEventListener不起作用。我做错了什么吗?

2个回答

21

每次绑定函数时,您都会得到一个新的函数。您正在从最初添加的不同侦听器中删除侦听器。存储function.bind的结果,并在两个地方使用它。

this.boundInfiniteScroll = this.infiniteScroll.bind(this);
...

  } else {
    window.removeEventListener('scroll', this.boundInfiniteScroll);
  }
}

window.addEventListener('scroll', this.boundInfiniteScroll);

太棒了。非常感谢。 - shet_tayyy

5
要使用 removeEventListener,您需要传递与您传递给 addEventListener 相同的函数引用。因为 .bind 是新函数,.bind 返回新引用,所以在您的示例中有两个不同的引用,这就是为什么 removeEventListener 不起作用的原因。

bind() 方法创建一个新函数,在调用时将其 this 关键字设置为提供的值,并在调用新函数时提供一系列参数。

let flag = true;
const infiniteScrollFn = infiniteScroll.bind(this);

function infiniteScroll() {
  let enterpriseWrap = $('.enterprise-blocks');
  let contentHeight = enterpriseWrap.offsetHeight;
  let yOffset = window.pageYOffset;
  let y = yOffset + window.innerHeight;

  if (this.props.hasMore) {
    if (y >= contentHeight && flag) {
      flag = false;

      this.props.loadMoreVendors(function() {
        flag = true;
      });
    }
  } else {
    window.removeEventListener('scroll', infiniteScrollFn);
  }
}

window.addEventListener('scroll', infiniteScrollFn);

示例


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