Javascript JS中的addEventListener未按预期工作
请先略读代码 index.html是:Javascript JS中的addEventListener未按预期工作,javascript,html,menu,addeventlistener,submenu,Javascript,Html,Menu,Addeventlistener,Submenu,请先略读代码 index.html是: <html><head><title>Home</title><script src="js/script.js"></script></head> <body onLoad="init()"> <ul class="sup" id="sup"> <li class="supitem"> <a href=
<html><head><title>Home</title><script src="js/script.js"></script></head>
<body onLoad="init()">
<ul class="sup" id="sup">
<li class="supitem">
<a href="#" class="supcont">Home<div class="v"></div></a>
<ul class="sub">
<li class="subitem"><a href="#" class="subcont">Home1</a></li>
<li class="subitem"><a href="#" class="subcont">Home2</a></li>
<li class="subitem"><a href="#" class="subcont">Home3</a></li>
</ul>
</li>
<li class="supitem">
<a href="#" class="supcont">Blog<div class="v"></div></a>
<ul class="sub">
<li class="subitem"><a href="#" class="subcont">Blog1</a></li>
<li class="subitem"><a href="#" class="subcont">Blog2</a></li>
<li class="subitem"><a href="#" class="subcont">Blog3</a></li>
</ul>
</li>
</ul>
</body>
</html>
主页
-
-
script.js是:
function init() {
var sky = 0;
var sup = document.getElementById("sup");
var supitems = sup.getElementsByClassName("supitem");
for (var i = 0, ln = supitems.length; i < ln; i++) {
var supconts = supitems[i].getElementsByClassName("supcont");
var subs = supitems[i].getElementsByClassName("sub");
var supcont = supconts[0];
supcont.innerHTML = "SuperMenu"+i;
if (subs.length > 0) {
var sub = subs[0];
supcont.addEventListener("click",function() {
toggleVisibility(sub); });
supcont.style.background = "#"+sky+sky+sky;
sub.style.background = "#"+sky+sky+sky;
sky += 4;
}
}
}
function toggleVisibility(object) {
object.style.visibility =
(object.style.visibility == "hidden" ?"visible" :"hidden");
}
函数init(){
var-sky=0;
var sup=document.getElementById(“sup”);
var supitems=sup.getElementsByClassName(“supitem”);
对于(变量i=0,ln=supitems.length;i0){
var sub=subs[0];
supcont.addEventListener(“单击”,函数(){
切换可见性(sub);});
supcont.style.background=“#”+天空+天空+天空;
sub.style.background=“#”+天空+天空+天空;
天空+=4;
}
}
}
函数切换可见性(对象){
object.style.visibility=
(object.style.visibility==“隐藏”?“可见”:“隐藏”);
}
我想做的是当我按下supermenu时,所有子菜单的可见性都被切换。但我不知道我在哪里犯了错误。当我按下Supmenu0时,Supmenu1的子菜单被切换,而不是Supmenu1的子菜单。提前谢谢
另外,我认为问题出在addEventListener中。这是一个常见问题,但我会尝试给出比我发现的更好的解释。当您将函数作为参数传递时(定义事件处理程序时),javascript此时不会计算函数,而是将函数与其父级
作用域的引用一起存储
在触发事件处理程序之前,不会对函数求值。此时,解释器将检查父范围
中的sub
的值。由于这总是在for
循环完成后发生,因此它总是会找到sub
的最后一个值,即当for
循环完成时sub
是什么。因此,所有事件侦听器都将使用sub
的最后一个值
我们可以通过创建一个。替换此项:
supcont.addEventListener("click",function() {
toggleVisibility(sub); });
为此:
(function(localSub) {
supcont.addEventListener("click",function() {
toggleVisibility(localSub);
});
})(sub);
这样做之所以有效,是因为我们通过调用IIFE将每个事件处理程序声明包装为一个新的父级scope
。这迫使事件处理程序在IIFE内保留范围的副本(称为在该范围上创建闭包)。现在,当事件处理程序查找localSub
时,它将在新的父范围中找到它,并且它将具有我们想要的值。这是一个常见问题,但我将尝试给出比我发现的更好的解释。当您将函数作为参数传递时(定义事件处理程序时),javascript此时不会计算函数,而是将函数与其父级作用域的引用一起存储
在触发事件处理程序之前,不会对函数求值。此时,解释器将检查父范围
中的sub
的值。由于这总是在for
循环完成后发生,因此它总是会找到sub
的最后一个值,即当for
循环完成时sub
是什么。因此,所有事件侦听器都将使用sub
的最后一个值
我们可以通过创建一个。替换此项:
supcont.addEventListener("click",function() {
toggleVisibility(sub); });
为此:
(function(localSub) {
supcont.addEventListener("click",function() {
toggleVisibility(localSub);
});
})(sub);
这样做之所以有效,是因为我们通过调用IIFE将每个事件处理程序声明包装为一个新的父级scope
。这迫使事件处理程序在IIFE内保留范围的副本(称为在该范围上创建闭包)。现在,当事件处理程序查找localSub
时,它将在新的父范围中找到它,并且它将具有我们想要的值。谢谢,先生。顺便说一句,我刚刚学会了什么是结束。在这里留下链接以防万一:)谢谢,先生。顺便说一句,我刚刚学会了什么是结束。将链接留在此处以防万一:)