Jquery setTimeout 正在制造问题,并且在循环中无法正常工作



我正在研究下面的代码片段。没有 setTimeOut(),它的工作完美,并在 loaded(id) 函数中向我显示 id。但是使用 setTimeOut() 这不能正常工作。

var menuLink = document.getElementsByClassName("li_common_class");
for(var i = 0; i <  5; i++ ) {
var childElement = menuLink[i];
childElement.addEventListener('click',setTimeout(function(){
loaded(childElement.id);
},100), true);
}
function loaded(id){
alert(id);
}

传递函数

您应该分配一个事件处理程序,但您要立即调用setTimeout

将函数传递给.addEventListener(),并使用const声明变量。

var menuLink = document.getElementsByClassName("li_common_class");
for (var i = 0; i < 5; i++) {
const childElement = menuLink[i];
childElement.addEventListener('click', function() {
setTimeout(function() {
loaded(childElement.id);
}, 100)
}, true);
}
function loaded(id) {
alert(id);
}

所以现在将函数作为第二个参数传递给.addEventListener.该函数被分配为子元素的事件处理程序。我还使用const声明了childElement,否则您将始终获得分配给该变量的最后一个值,而不是每个循环迭代的相应值。


无需闭包参考

但是,这仍然不理想。您真的根本不需要childElement,因为您已经在处理程序中引用了该元素。

var menuLink = document.getElementsByClassName("li_common_class");
for (var i = 0; i < 5; i++) {
menuLink[i].addEventListener('click', function(event) {
var targ = event.currentTarget
setTimeout(function() {
loaded(targ.id);
}, 100)
}, true);
}
function loaded(id) {
alert(id);
}

现在看到我向处理程序函数添加了一个event参数。这使您可以获取处理程序绑定到的元素。

我们本可以使用this而不是event.currentTarget,但我们实际上在setTimeout回调中丢失了该值。如果我们将箭头函数传递给setTimeout,那么事件处理程序的this就可以访问。


重用函数

但是,由于不再需要将函数与循环的每次迭代相关联,因此我们实际上可以将函数移动到循环之外,以便重用它。

var menuLink = document.getElementsByClassName("li_common_class");
for (var i = 0; i < menuLink.length; i++) {
menuLink[i].addEventListener('click', handler, true);
}
function handler(event) {
var targ = event.currentTarget
setTimeout(function() {
loaded(targ.id);
}, 100)
}
function loaded(id) {
alert(id);
}
<ul>
<li class="li_common_class" id="foo">CLICK ME</li>
<li class="li_common_class" id="bar">CLICK ME</li>
<li class="li_common_class" id="baz">CLICK ME</li>
</ul>


ES6

如果我们要使用 ES6,可以大大缩短相同的代码:

const menuLinkOnClick = event => setTimeout(() => alert(event.target.id), 100),
menuLinks       = document.getElementsByClassName("li_common_class");
for (let menuLink of menuLinks) {
menuLink.addEventListener('click', menuLinkOnClick);
}

试试这个:

var menuLink = document.getElementsByClassName("li_common_class");
for (var i = 0; i < 5; i++) {
var childElement = menuLink[i];
(function (ce) {
ce.addEventListener('click', function () {
setTimeout(function () {
loaded(ce.id);
}, 100);
}, true);
})(childElement);
}
function loaded(id) {
alert(id);
}

试试这个:

var menuLink = document.getElementsByClassName("li_common_class");
for(i = 0; i <  5; i++) {
var childElement = menuLink[i];
childElement.addEventListener('click', function(){setTimeout(function(){loaded(childElement.id)},100)}, true);
}
function loaded(id){
alert(id);
}

你在 addEventListener() 中有一个函数 (setTimeout),但它没有放在 " 或 function(){} 中。您需要它在其中之一中,除非您希望它通过放置不带引号的 functionName 或 () 来调用没有参数的函数。

希望这有效。

最新更新