在循环中添加事件监听器(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>
备注:
- 改为使用
mouseover
和 mouseout
事件
- 不要使用e.srcElement,使用e.target(标准)
- 不需要在 querySelectionAll 之后检查 nodeList(最坏的情况,你会得到一个空列表,forEach 什么都不做)
- 不要声明内联事件处理程序(更好的性能)
我有一个图片网格,用户可以将鼠标悬停在上面进行预览。我能够在一个循环中为每个人添加一个监听器。如果用户在项目上至少 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>
备注:
- 改为使用
mouseover
和mouseout
事件 - 不要使用e.srcElement,使用e.target(标准)
- 不需要在 querySelectionAll 之后检查 nodeList(最坏的情况,你会得到一个空列表,forEach 什么都不做)
- 不要声明内联事件处理程序(更好的性能)