removeEventListener似乎不起作用?

时间:2017-07-20 00:10:36

标签: javascript dom

出于某种原因,我需要在滚动页面结束时延迟click和preventDefault一段时间。所以我写了这样的东西:

// const disableClickDuringScrollHandler=(e)=> {
//      e.preventDefault();
//    };
this.scrollHandler = e => {
  console.log('scrolling');
  const disableClickDuringScrollHandler = (e) => {
    e.preventDefault();
  };
  document.addEventListener('click', disableClickDuringScrollHandler);
  window.clearTimeout(this.scrollTimer);
  this.scrollTimer = window.setTimeout(() => {
    console.log('scroll end');
    document.removeEventListener('click', disableClickDuringScrollHandler);
  }, 300);
}
window.addEventListener('scroll', this.scrollHandler);

我也写了一个codepen:https://codepen.io/zhangolve/pen/gRNMoX

我的问题是当我在scrollHandler之外放置disableClickDuringScrollHandler时,removeEventListener可以很好地工作,但是当我在scrollHandler中放入disableClickDuringScrollHandler时,removeEventListener似乎无法工作。

我已经多次尝试找到原因但却失败了。所以我来到这里寻求你的帮助。

1 个答案:

答案 0 :(得分:1)

问题是每次用户滚动时,都会创建一个新的disableClicksDuringScroll闭包并将其添加为单击侦听器。当这个计时器运行时,它会删除最新的点击监听器,但不会删除以前的点击监听器(因为它们是不同的闭包,所以它们不等于你这次删除的功能)。

您应该在disableClicksDuringScroll处理程序之外只定义一次scroll函数,因为它不引用任何局部变量。然后当你致电removeEventListener时,它会找到这个处理程序。

您也可以使用变量,这样您只需在滚动开始时添加一次点击侦听器,而不是每次重置计时器时都会添加。

this.disableClickDuringScrollHandler = (e) => {
  e.preventDefault();
};

this.inScroll = false;

this.scrollHandler = e => {
  console.log('scrolling');
  if (!this.inScroll) {
    document.addEventListener('click', this.disableClickDuringScrollHandler);
    this.inScroll = true;
  }
  window.clearTimeout(this.scrollTimer);
  this.scrollTimer = window.setTimeout(() => {
    this.inScroll = false;
    console.log('scroll end');
    document.removeEventListener('click', disableClickDuringScrollHandler);
  }, 300);
}
window.addEventListener('scroll', this.scrollHandler);