首页 > 解决方案 > 两个事件同时触发时如何控制执行顺序

问题描述

这是一个简单的下拉菜单,包含inputHTML 和纯 JavaScript(无 JQuery)。我不想使用带有选项标签的预定义 HTML 列表,因为我需要滚动条、样式等。

我隐藏了列表onblur,但是在单击项目列表之前触发了此事件。所以结果是我无法单击下拉菜单的项目,因为列表事先被隐藏了。

这是代码:

function showList(){
    elem = document.getElementById("list");
  elem.className = "unhidden";
}

function hideList(){
    elem = document.getElementById("list");
  elem.className = "hidden";
}

function showSuccess(){
    elem = document.getElementById("successDiv");
  elem.innerHTML = "code successful!";
}
.hidden { display: none; }
.unhidden { display: block; }
<html>
  <head>
  
  </head>
  <body>
    
    <input onfocus="showList();" onblur="hideList();"/>
    
    <div id="list" class="hidden">
      <a href="#" onclick="showSuccess();">click for success</a>
    </div>
    
    <div id="successDiv">
    </div>
    
  </body>
</html>

标签: javascripthtmldrop-down-menu

解决方案


最简单的解决方案是在隐藏元素之前使用setTimeout添加一个小的延迟。在下面的示例中,我在删除类之前等待了 250 毫秒。

function showList(){
  elem = document.getElementById("list");
  elem.className = "unhidden";
}

function hideList(){
  setTimeout(function() {
    elem = document.getElementById("list");
    elem.className = "hidden";
  }, 250); // Wait 250 milliseconds
}

function showSuccess(){
  elem = document.getElementById("successDiv");
  elem.innerHTML = "code successful!";
}
.hidden { display: none; }
.unhidden { display: block; }
<html>
  <head>
  
  </head>
  <body>
    
    <input onfocus="showList();" onblur="hideList();"/>
    
    <div id="list" class="hidden">
      <a href="#" onclick="showSuccess();">click for success</a>
    </div>
    
    <div id="successDiv">
    </div>
    
  </body>
</html>

编辑:更强大的解决方案

您可以查看相关事件如果它在列表中,请在单击它之前不要关闭它。

const input = document.querySelector("#input");
const list = document.querySelector("#list");
const listItems = document.querySelectorAll("#list a");
const success = document.querySelector("#successDiv");

input.addEventListener("focus", showList);
input.addEventListener("blur", hideList);

for(const listItem of listItems) {
  listItem.addEventListener("click", showSuccess);
}

function showList() {
  list.classList.remove("hidden");
}

function hideList(event) {
  if(event.relatedTarget?.parentNode !== list) {
    list.classList.add("hidden");
  }
}

function showSuccess(event) {
  success.innerHTML = "code successful!";
  
  // Remove line to keep list open
  hideList(event);
}
#list {
  display: flex;
  flex-direction: column;
}

#list.hidden { display: none; }
<input id="input" />

<div id="list" class="hidden">
  <a href="#">click for success</a>
  <a href="#">click for more success</a>
  <a href="#">click for even more success</a>
</div>

<div id="successDiv">
</div>


推荐阅读