点击被触发而没有预期的点击?

时间:2019-04-07 13:01:38

标签: javascript

简而言之,我在addEventListener中有addEventListener。我正在听的事件是click。这是我的代码示例:

function toggleElement() {
    // function stuff
}

anchor.addEventListener('click', (e) => {
    e.preventDefault();

    if (!anchorWrapper.classList.contains('active')) {
        // do some stuff
        window.addEventListener('click', toggleElement, false);
    } else {
        // do some stuff
        window.removeEventListener('click', toggleElement, false);
    }
});

每次单击锚元素时,我都会将一个事件侦听器分配给侦听单击的窗口。我希望用户单击锚点,锚点又不应初始化toggleElement,而只是将事件侦听器分配给窗口。然后,根据我的想法(事实证明是错误的),应仅在下次在窗口的任何位置第二次单击时才初始化该函数。但是,它是通过单击锚元素来运行的。

我不正确是什么?如何防止用户单击锚元素时toggleElement函数未初始化,而是等待窗口上的click事件?

3 个答案:

答案 0 :(得分:2)

问题在于,您的第一个事件是从DOM到propagating,直到您刚刚向其添加事件处理程序的节点(在您的情况下是窗口)。因为传播将在回调退出后继续进行,这意味着添加第二个事件处理程序后,它将触发第二个事件处理程序。

您可以通过在事件中使用stopPropagation方法来避免这种情况。您还可以使用其他技术(例如promise或零长度超时)将其释放给引擎中的下一个JS“任务”,但是还有一些您不想这样做的原因。

我在这里创建了一些示例代码,它还处理了您希望按钮(或其他按钮)内的后续单击也触发第二个事件处理程序的情况。还要注意,我正在让第二个事件处理程序注销自己,这使此逻辑稍微简单一些。

let target = document.getElementById("target");
let targetWrapper = document.getElementById("targetWrapper");

function secondFunction() {
    console.log("Called second callback");
    //alert("Second Function Called");
    
    targetWrapper.removeEventListener('click', secondFunction, false);
    targetWrapper.classList.remove("active");
}

target.addEventListener('click', (e) => {
	console.log("Called first callback")

    e.preventDefault();
    
    
    if(!targetWrapper.classList.contains("active")){
    	targetWrapper.addEventListener('click', secondFunction, false);
      targetWrapper.classList.add("active");
      e.stopPropagation();
    }
});
body {
  font-size: 20px;
  font-family:sans-serif;
}

#targetWrapper {
  min-height: 400px;
  min-width: 400px;
  text-align: center;
  background-color: green;
  position:relative;
}

#target {
  vertical-align: middle;
  background-color:blue;
  color:red;
  padding:50px;
  position:absolute;
  top:100px;
  left:50px;
}

#targetWrapper.active{
  outline: 3px solid red;
}
<div id="targetWrapper">
  <a id="target">
  Click me!
  
  </a>
</div>

有关事件传播和处理程序的更多信息:

DOM level 3 events

A question I answered earlier about order of event handling

Example of event propagation

答案 1 :(得分:1)

toggleElement是否获得“旧”点击事件?尝试将其设置为零超时:

setTimeout(function() { window.addEventListener('click', toggleElement, false); });

答案 2 :(得分:1)

也许代码比您的点击更快?我认为单击时会分配事件侦听器,但您仍在“单击”,因此第二个事件侦听器也会检测到该单击。如果我错了请纠正我。

尝试将e.stopPropagation();放在e.preventDefault();之后。