在循环中添加事件监听器(mouseenter)但仅在 1500 毫秒后触发 - clearTimeout 问题

Adding eventListeners in a loop (mouseenter) but only triggering after 1500ms - issue with clearTimeout

我有一个图片网格,用户可以将鼠标悬停在上面进行预览。我能够在一个循环中为每个人添加一个监听器。如果用户在项目上至少 1.5 秒,我只想触发我的逻辑。我无法确定为什么我的 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 秒内鼠标离开,我永远无法摆脱我的计时器。

谢谢

变量 "timer" 在清理函数中不可见。它是 "mouseenter" 事件函数的私有变量。

在函数外声明计时器,以便其他函数可以访问。

(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 什么都不做)
  • 不要声明内联事件处理程序(更好的性能)