两个事件同时触发时如何控制执行顺序
How to control execution order when two events are triggered at the same time
这是一个简单的下拉菜单,在HTML中有input
和纯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>
最简单的解决方案是在隐藏元素之前使用 setTimeout 添加一个小的延迟。在下面的示例中,我在删除 class.
之前等待 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>
编辑:更强大的解决方案
您可以查看事件 relatedTarget,如果它在列表中,请在单击它之前不要关闭它。
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>
这是一个简单的下拉菜单,在HTML中有input
和纯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>
最简单的解决方案是在隐藏元素之前使用 setTimeout 添加一个小的延迟。在下面的示例中,我在删除 class.
之前等待 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>
编辑:更强大的解决方案
您可以查看事件 relatedTarget,如果它在列表中,请在单击它之前不要关闭它。
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>