提问人:nicoiscoding 提问时间:8/23/2023 最后编辑:nicoiscoding 更新时间:8/24/2023 访问量:104
单击外部时关闭下拉按钮,但性能良好
Close dropdown button when clicking outside but with good performance
问:
我一直在尝试制作一个下拉按钮,当它点击它外面时它会停用,但我没有找到性能良好的好解决方案,我正在使用 Astro 框架制作网站
所以这是我希望它是什么样子的一个例子:例子
这就是我所拥有的:我的网站
这是我的代码:
<nav
class="hidden items-center lg:relative lg:mt-0 lg:!flex lg:basis-auto"
>
<!-- Desktop Navigation -->
<ul
class="list-style-none mr-auto flex flex-col pl-0 lg:flex-row"
>
{navData.map(data => {
if(data.dropdown === true) {
return (
<li data-title={data.title} class="sm:block relative dropdowns mx-2 lg:flex ">
<button data-title={data.title} class="dropdown text-sm rounded flex gap-1 items-center">
{data.title}
<svg viewBox="0 0 1024 1024" class="icon w-3" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="currentColor"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M903.232 256l56.768 50.432L512 768 64 306.432 120.768 256 512 659.072z" ></path></g></svg>
</button>
<div data-title={data.title} class="absolute right-0 top-7 mt-2 w-48 bg-gray-800 rounded-md overflow-hidden z-10 hidden">
{data.subcat.map(el => (
<a href={el.slug} class="block px-4 py-2 text-sm text-gray-200 hover:bg-gray-700">
{el.title}
</a>
))}
</div>
</li>
)}
else {
return (
<li class="mb-4 pl-2 lg:mb-0 lg:pl-0 lg:pr-1" data-te-nav-item-ref>
<a
class="p-0 text-sm transition duration-200 hover:ease-in-out motion-reduce:transition-none lg:px-2"
href={`${data.slug}`}
data-te-nav-link-ref
>
{data.title}
</a>
</li>
)
}
})}
</ul>
</nav>
const dropdownToggle = document.querySelectorAll('.dropdown');
const dropdownMenu = document.querySelectorAll('.dropdowns > div');
dropdownToggle.forEach(button => button.addEventListener('click', () => {
dropdownMenu.forEach((el) => {
if(button.getAttribute('data-title') === el.getAttribute('data-title')){
el.classList.toggle('hidden')
}
});
}))
我尝试使用focus-within,但没有按预期工作
.dropdowns:focus-within > div {
display: block;
}
我认为这个解决方案:
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
对性能不利
答:
0赞
Lajos Arpad
8/24/2023
#1
这对性能来说还不错,因为您需要一个点击处理程序,每当要关闭下拉列表时,它都会注意到。你不应该优化那些不慢的东西,因为你有可能用一些难以维护的东西使你的代码过于复杂,而且可能也更慢。
但是,如果您确实注意到一些性能问题(例如,当您有数千个下拉列表时),那么您可以简单地创建一些资源,为了简单起见,让我们调用:currentDropdown
- 每当发生单击时,如果之前设置了该下拉列表,并且该下拉列表与您刚刚打开的下拉列表不匹配(如果您打开了下拉列表),则将其折叠
currentDropdown
- 每当打开下拉菜单时,只需将其设置为它
currentDropdown
- 每当单击发生在任何下拉列表之外时,请确保不要忘记设置为
currentDropdown
undefined
- 如果需要在选择下拉列表中的项目后关闭下拉列表,则还要设置为
currentDropdown
undefined
因此,您最多只能处理一个下拉列表,而不是循环所有下拉列表。
如果你真的想避免在下拉列表没有打开的情况下在下拉列表之外出现点击事件(但我不建议这样做),那么你可以在任何下拉列表之外单击时,这样下拉菜单之外的点击就不会在你不需要的时候触发事件侦听器。但是,同样,我不建议这样做,因为它是代码复杂性,几乎没有任何收益。避免如上所述的循环就足够了。removeEventListener
评论
.contains()