在循环(mouseenter)中添加eventListener,但仅在1500毫秒后触发-clearTimeout问题

时间:2019-01-11 23:50:09

标签: javascript settimeout addeventlistener nodelist cleartimeout

我有一个图像网格,用户可以将鼠标悬停在图像网格上进行预览。我可以在一个循环中向每个侦听器添加一个侦听器。我只想在用户超过该项目1.5秒以上时触发我的逻辑。我无法确定为什么尝试清除timerTimeout的mouseleave事件实际上并未清除它。

我在代码中添加了注释,以澄清:

(function () {
  var nodeList = document.querySelectorAll('div.MyDiv > img') || undefined;
  if (nodeList) {
    nodeList.forEach(function (_el, idx) {
      _el.addEventListener("mouseenter", function (e) {
        var _imgsrcga = e.srcElement.src;
         var timer = setTimeout(function() {
            console.log('This ran'); // this is OK after 1.5 seconds, but it ALWAYS runs after 1.5 seconds
        }, 1500)
      }, false);

      // not clearing the timer....
      _el.addEventListener("mouseleave", function(e) {
        console.log('cleared')
        clearTimeout(timer) // my timer never clears with a mouseleave event
      })
    })
  }
})();

因此:实际上,我的console.log('this ran')确实延迟了1.5秒,但是如果它们在不到1.5秒的时间内鼠标离开,我将永远无法摆脱它的计时器。

谢谢

2 个答案:

答案 0 :(得分:2)

变量“计时器”在清洁功能中不可见。它是“ mouseenter”事件函数的私有变量。

答案 1 :(得分:1)

在该功能之外声明计时器,以便其他功能可以使用该计时器。

(function () {
  var timer;
  var nodeList = document.querySelectorAll('div.MyDiv > img') || undefined;
  if (nodeList) {
    nodeList.forEach(function (_el, idx) {
      _el.addEventListener("mouseenter", function (e) {
        var _imgsrcga = e.srcElement.src;
         timer = setTimeout(function() {
            console.log('This ran'); 
        }, 1500)
      }, false);

      _el.addEventListener("mouseleave", function(e) {
        console.log('cleared')
        clearTimeout(timer)
      })
    })
  }
})();
<div class="MyDiv">
  <img src="http://placekitten.com/g/200/300">
</div>

我提供了编写这段代码的方式。我认为,为了便于阅读和理解,您的代码可以采用不同的结构。我也删除了一些不必要的行,并使用了ES6语法。

(function () {
  let timer;
  let nodeList = document.querySelectorAll('div.MyDiv > img');

  const mouseOver = e=> {
    let _imgsrcga = e.target.src;
    timer = setTimeout( ()=> console.log('This ran'), 1500)
  };
  const mouseOut = e=> {
    console.log('cleared')
    clearTimeout(timer)
  };
    
  nodeList.forEach( _el=>{
    _el.addEventListener("mouseover", mouseOver , false);
    _el.addEventListener("mouseout", mouseOut);
  });
  
})();
<div class="MyDiv">
  <img src="http://placekitten.com/g/200/300">
</div>

注意:

  • 改为使用mouseovermouseout事件
  • 不要使用e.srcElement,请使用e.target(标准)
  • 在querySelectionAll之后不需要检查nodeList(最坏的情况是,您将有一个空列表,forEach将不执行任何操作)
  • 不要声明内联事件处理程序(性能更好)