我知道这是一个常见问题,但我所见过的答案都没有解决我的问题,如果我错过了一个答案,我深表歉意,这显然可以被删除/标记为重复......
标记
<div class="has-dropdown">
<button class="js-dropdown-trigger">
Dropdown
</button>
<div class="dropdown">
<div class="dropdown__item">
Some random text with a <a href="#" class="stop-propagation">link</a> in it.
</div>
<div class="dropdown__divider"></div>
<div class="dropdown__item">
<a href="#">Item One</a>
</div>
<div class="dropdown__item">
<a href="#">Item Two</a>
</div>
<div class="dropdown__item">
<a href="#">Item Three</a>
</div>
</div>
</div>
脚本
$('.has-dropdown').off().on('click', '.js-dropdown-trigger', (event) => {
const $dropdown = $(event.currentTarget).next('.dropdown');
if (!$dropdown.hasClass('is-active')) {
$dropdown.addClass('is-active');
} else {
$dropdown.removeClass('is-active');
}
});
$('.has-dropdown').on('focusout', (event) => {
const $dropdown = $(event.currentTarget).children('.dropdown');
$dropdown.removeClass('is-active');
});
造型
.has-dropdown {
display: inline-flex;
position: relative;
}
.dropdown {
background-color: #eee;
border: 1px solid #999;
display: none;
flex-direction: column;
position: absolute;
top: 100%;
left: 0;
width: 300px;
margin-top: 5px;
}
.dropdown.is-active {
display: flex;
}
.dropdown__item {
padding: 10px;
}
.dropdown__divider {
border-bottom: 1px solid #999;
}
小提琴
http://jsfiddle.net/joemottershaw/3yzadmek/
它非常简单,单击js-dropdown-trigger
切换下拉类很好,单击容器is-active
外部也会删除下拉类。has-dropdown
is-active
除了,我期望发生的是关注元素的后代元素(单击或选项卡),has-dropdown
这意味着focusout
不应触发事件处理程序,因为您仍然专注于has-dropdown
容器的后代元素。
当某个元素或其中的任何元素失去焦点时,该
focusout
事件将被发送到该元素。这与 blur 事件不同,它支持检测对后代元素的焦点丢失
我知道我可以删除focusout
事件处理程序并使用类似的东西:
$(document).on('click', (event) =>{
const $dropdownContainer = $('.has-dropdown');
if (!$dropdownContainer.is(event.target) && $dropdownContainer.has(event.target).length === 0) {
$dropdownContainer.find('.dropdown').removeClass('is-active');
}
});
这可行,但是如果您要单击触发器,然后通过选项卡浏览链接,则当您通过最后一个链接进行选项卡时,下拉菜单仍然可见。只是努力寻找最佳解决方案来保持事物的可访问性。
如果可能的话,我想坚持这种focusout
方法。
根据darshanags答案更新
尽管更新后的脚本适用于单个元素,但添加其他元素body
会导致focusout
不再按预期工作。我认为这是因为即使将焦点应用于容器之后的任何元素,而不仅仅是后代,该if
语句似乎也是正确的?has-dropdown
因为如果您要更新 HTML 并在下拉菜单后添加更多可聚焦元素,例如输入。当从has-dropdown
容器内的最后一个可聚焦元素切换到输入时,下拉菜单保持活动状态。它仅在下拉列表是 DOM 中的最后一个元素时才有效,并且仅在焦点完全失去 DOM 时触发。