使用普通JavaScript和ARIA角色关闭外部单击下拉列表

使用普通JavaScript和ARIA角色关闭外部单击下拉列表,javascript,Javascript,我一直在尝试创建一个非常基本的下拉菜单,但无法获得外部隐藏点击部分的权利。我已经经历了多次迭代,但最终总是无法正确地关闭它,或者在激活另一个下拉列表时关闭其他打开的下拉列表。这是我的最新版本 功能菜单(触发器){ 让expanded=trigger.getAttribute(“aria expanded”)==“true”| | false; let menu=trigger.nextElementSibling; setAttribute(“aria expanded”,!expanded)

我一直在尝试创建一个非常基本的下拉菜单,但无法获得外部隐藏点击部分的权利。我已经经历了多次迭代,但最终总是无法正确地关闭它,或者在激活另一个下拉列表时关闭其他打开的下拉列表。这是我的最新版本

功能菜单(触发器){
让expanded=trigger.getAttribute(“aria expanded”)==“true”| | false;
let menu=trigger.nextElementSibling;
setAttribute(“aria expanded”,!expanded);
menu.hidden=!menu.hidden;
}
const menuTriggers=document.queryselectoral(“.menu触发器”);
menuTrigger.forEach((menuTrigger)=>{
menuTrigger.addEventListener(“单击”,()=>{
菜单(menuTrigger);
});
});
菜单

您必须侦听窗口对象上的鼠标向下事件,以检测关闭单击,并且只有在下拉菜单本身不包含event.target时才关闭下拉菜单

功能菜单(触发器)
{
让expanded=trigger.getAttribute(“aria expanded”)==“true”| | false;
let menu=trigger.nextElementSibling;
setAttribute(“aria expanded”,!expanded);
menu.hidden=!menu.hidden;
如果(!menu.hidden)
{
设置超时(()=>
{
让eventType=“mousedown”;
let handler=(e)=>
{
if(trigger!==e.target&&!menu.contains(e.target))
{
菜单(触发器);
}
removeEventListener(事件类型,处理程序,false);
};
addEventListener(事件类型,处理程序,false);
}, 0);
}
}
const menuTriggers=document.queryselectoral(“.menu触发器”);
menuTrigger.forEach((menuTrigger)=>
{
menuTrigger.addEventListener(“单击”,()=>
{
菜单(menuTrigger);
});
});

菜单

谢谢您的回答。我将尝试处理
菜单()
函数内部的外部单击,以建立更清晰的组件定义。没问题,我编辑了答案,将代码移动到
菜单()
函数中。立即尝试。谢谢你的提示!据我所知,
setTimeout()
不是必需的;对吗?另一个条件需要添加为
handler()
的一部分,以便允许遵循链接:
!触发器。包含(如目标)和&!menu.contains(e.target)
。您可能会发现在某些情况下设置超时是必要的。它防止按钮单击在同一次单击过程中也触发mousedown事件。奇怪,但我在一些浏览器中见过这种情况。
ul
元素是一个块元素,不可见地跨越整个屏幕宽度。为了解决这个问题,我将html包装在
内联块
中。你会弄清楚细节;这对你来说只是一个开始。再次感谢你的帮助。实际上,防止多个事件触发似乎是必要的,不管是
setTimeout()
还是各种条件语句。