Javascript 正在执行但未显示效果的事件处理程序
我正在开发一个基于Javascript的绘画应用程序,现在我正在制作一个菜单,就像客户端区域是一个桌面窗口一样 当然,在这个菜单中,我有一些主选项卡,它们的下拉列表包含所有项目,有时子选项卡会导致子下拉列表。对于我的问题,让我们关注主要选项卡(如“文件”或“编辑”)。简而言之,问题在于他们不会通过显示下拉列表来做出反应 在初始化页面的过程中,我按类获取所有元素:Javascript 正在执行但未显示效果的事件处理程序,javascript,drop-down-menu,dom-events,Javascript,Drop Down Menu,Dom Events,我正在开发一个基于Javascript的绘画应用程序,现在我正在制作一个菜单,就像客户端区域是一个桌面窗口一样 当然,在这个菜单中,我有一些主选项卡,它们的下拉列表包含所有项目,有时子选项卡会导致子下拉列表。对于我的问题,让我们关注主要选项卡(如“文件”或“编辑”)。简而言之,问题在于他们不会通过显示下拉列表来做出反应 在初始化页面的过程中,我按类获取所有元素: MTabs = menubar.getElementsByClassName('mainTab'); 然后添加事件处理程序。我传递
MTabs = menubar.getElementsByClassName('mainTab');
然后添加事件处理程序。我传递给addEventListener()的函数由一个中介函数返回,该函数将特定函数与处理程序所针对的节点的节点引用组合在一起。我发现了一个(“臭名昭著的循环问题”->“工作引用”),它显示了这种处理从循环中添加事件处理程序的方法。以下是对addEventListener(
)的调用:
全局布尔变量menuClicked
告诉用户是否单击了菜单。如果为true,菜单元素应对鼠标悬停事件作出反应,并显示正确的下拉列表。单击选项卡时(在“工具”选项卡上方的图像中),此变量在openMenu()
中设置为true。奇怪的是,函数返回后,变量再次为false。我通过console.log()
跟踪注意到了这一点。此外,未显示下拉列表。我希望这能起作用(以前有过),因为代码非常简单:
var setActive = function(node){
// Adding css class that sets visibility:visible for dropdowns
node.classList.add('menuActive');
}
在我看来,处理程序似乎没有设置实际的全局menuClicked
变量,但为什么不呢?或者函数是否在if语句中返回带有menuClicked
硬编码为false的处理程序
我已经尝试了很多方法,但我仍然想知道为什么这不起作用。我想我已经迷失在JavaScript所要求的自由中了……:)
我做了一个
您在添加事件处理程序时所做的工厂操作并不像我认为的那样。函数在分配处理程序时执行,导致在与页面进行任何交互之前执行多次。我将重构它,以便在事件处理期间找到事件目标。更直截了当
所以,而不是
node.addEventListener('mouseover', onMouseOver_STabs(node));
执行此操作以分配处理程序
node.addEventListener('mouseover', onMouseOver_STabs);
然后,处理程序应该接受单个参数“event”,并使用它来查找事件的目标
var node = event.target;
至于menuClicked var,我认为这正如您预期的那样起作用,但另一个因素使其不可预测;单击事件正在从选项卡传播到“菜单\后台”,导致在“openMenu”之后立即调用“quitMenu”
添加
event.stopPropagation();
在您的事件处理程序中,将防止这种情况,就像我在您的小提琴叉中所做的那样。请看
以获得更深入的解释
另外,重要的是,我认为不能使用addEventListener将处理程序附加到窗口加载。有几种方法可以用来初始化全局变量,但我会删除它们
//doesn't work
window.addEventListener('load',initMain);
并将初始化代码移动到另一个脚本标记,就在html之前
</body>
标签。或者,将整个脚本移到那里,并将初始化代码移到所有脚本的底部。这并没有很好地反映在我的提琴中,因为它都在一个框中,我认为JSFIDLE将一个window.onload包装在它的周围。做了一个JSFIDLE,它只包含CSS菜单和一种检测点击动作的方法。也许这个例子有助于在这种方法的基础上进一步发展 HTML JS
你能为菜单添加html吗,这样我们就更容易复制或分析正在发生的事情了?或者,如果您可以创建一个显示问题的工作代码段,那么更好的方法是将
菜单单击设置为true
?还有什么是deactivateMenu()
?@SarveshKumarSingh menuClicked由openMenu()设置为true,由quitMenu()设置为false。deactivateMenu()隐藏所有菜单元素,在quitMenu()中也被称为deactivateMenu()div
,li
或者什么?@SarveshKumarSingh他们是span
。非常感谢你的例子,对我来说这看起来更“干净”。不过,我还不是CSS专业人士,你的方法没有告诉我为什么我自己的Javascript方法不起作用,我的问题是关于。。。我可能会考虑在使用CSS自我教育后使用你的方式,但是我想知道我的JavaScript有什么不对。哇,我一看到它就有意义了。我不知道是什么打破了我的剧本,这个项目我几个月前就已经放弃了。感谢(来自业余爱好者)您的全面回答!
//doesn't work
window.addEventListener('load',initMain);
</body>
<ul class="menu">
<li>
<span>File</span>
<ul>
<li action="open">Open</li>
<li action="save">Save</li>
</ul>
</li>
<li>
<span>Edit</span>
<ul>
<li action="copy">Copy</li>
<li action="paste">Paste</li>
</ul>
</li>
</ul>
* {
font-family:"Helvetica Neue";
font-size: 14px;
}
body {
background: grey;
}
ul {
height: 16px;
list-style-type: none;
margin: 0;
padding: 5px 20px;
background: rgba(0, 0, 0, .25);
color: white;
}
ul.menu li {
float: left;
display: inline;
margin: 0 30px 0 0;
}
ul.menu li:hover ul, ul.menu li ul:hover {
display: block;
}
ul.menu li > ul {
display: none;
height: auto;
position: absolute;
top: 34px;
background: rgba(0, 0, 0, .25);
list-style-type: none;
margin: 0;
padding: 5px;
}
ul.menu li > ul li {
display: block;
float: none;
padding: 5px;
}
ul.menu li > span {
padding: 5px 0;
}
ul.menu li.show > ul {
display: block;
}
var menu = document.querySelectorAll('ul.menu')[0];
menu.addEventListener('click', function (event) {
var target = event.target;
var action = target.getAttribute("action");
// now do something with action
alert(action);
});