Javascript 正在执行但未显示效果的事件处理程序

Javascript 正在执行但未显示效果的事件处理程序,javascript,drop-down-menu,dom-events,Javascript,Drop Down Menu,Dom Events,我正在开发一个基于Javascript的绘画应用程序,现在我正在制作一个菜单,就像客户端区域是一个桌面窗口一样 当然,在这个菜单中,我有一些主选项卡,它们的下拉列表包含所有项目,有时子选项卡会导致子下拉列表。对于我的问题,让我们关注主要选项卡(如“文件”或“编辑”)。简而言之,问题在于他们不会通过显示下拉列表来做出反应 在初始化页面的过程中,我按类获取所有元素: MTabs = menubar.getElementsByClassName('mainTab'); 然后添加事件处理程序。我传递

我正在开发一个基于Javascript的绘画应用程序,现在我正在制作一个菜单,就像客户端区域是一个桌面窗口一样

当然,在这个菜单中,我有一些主选项卡,它们的下拉列表包含所有项目,有时子选项卡会导致子下拉列表。对于我的问题,让我们关注主要选项卡(如“文件”或“编辑”)。简而言之,问题在于他们不会通过显示下拉列表来做出反应

在初始化页面的过程中,我按类获取所有元素:

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);
});