javascript - 在没有预期点击的情况下触发了点击?

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

每次点击 anchor 元素时,我都会为监听点击的窗口分配一个事件监听器。我希望用户单击 anchor ,而 anchor 不应该初始化 toggleElement,而只是为窗口分配一个事件监听器。然后,根据我的想法(结果证明是错误的),该函数应该只在下一次、第二次单击窗口上的任意位置时初始化。但是,它会在单击 anchor 元素时运行。

我哪里不对?如何防止 toggleElement 函数在用户单击 anchor 元素时未初始化,而是等待窗口上的 click 事件?

最佳答案

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

您可以使用 stopPropagation 来避免这种情况您的事件中的方法。您还可以使用一些其他技术,例如 promise 或零长度超时,将其委托(delegate)给引擎中的下一个 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

关于javascript - 在没有预期点击的情况下触发了点击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55559278/

相关文章:

javascript - 将对象声明为参数不起作用?

javascript - 如何存储 'this' 元素供以后使用

javascript - window.open 与 form.submit

javascript - Protractor 函数助手生成相同的东西

javascript - Node js reSTLer 在发出 2 个不同的 API 请求时返回相同的结果

javascript - 测试 jQuery 插件的资源/技术/注意事项?

javascript - 单个 where() 条件导致查询不返回任何内容

javascript - 编译成 CommonJS 不会产生 NodeJS 可用的文件

javascript - Angular 选择类 if else

javascript - 从数据库存储和检索时 FullCalendar 日期不同