You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Phoenix框架侧边栏下拉菜单点击项后保持展开的实现

Phoenix + Tailwind + Flowbite 侧边栏下拉菜单点击后保持展开的解决方案

问题说明

我基于Phoenix框架构建应用,搭配Tailwind CSS和Flowbite组件库。侧边栏的下拉菜单在点击菜单项时会自动收起,用户体验不佳。尝试过使用Flowbite的ignoreClickOutsideClass选项但不清楚用法,自行编写的JavaScript代码也未达到预期效果,需求是点击下拉菜单项后菜单保持展开状态。

现有代码

HTML 结构

<button
  type="button"
  class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700"
  aria-controls="dropdown-layouts-router-api-config"
  data-collapse-toggle="dropdown-layouts-router-api-config"
>
  <svg 
    class="flex-shrink-0 w-6 h-6 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-400 dark:group-hover:text-white" 
    aria-hidden="true" 
    xmlns="http://www.w3.org/2000/svg" 
    fill="currentColor" 
    viewBox="0 0 24 24"
  >
    <path fill-rule="evenodd" d="M12 8a1 1 0 0 0-1 1v10H9a1 1 0 1 0 0 2h11a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1h-8Zm4 10a2 2 0 1 1 0-4 2 2 0 0 1 0 4Z" clip-rule="evenodd"/>
    <path fill-rule="evenodd" d="M5 3a2 2 0 0 0-2 2v6h6V9a3 3 0 0 1 3-3h8c.35 0 .687.06 1 .17V5a2 2 0 0 0-2-2H5Zm4 10H3v2a2 2 0 0 0 2 2h4v-4Z" clip-rule="evenodd"/>
  </svg>

  <span class="flex-1 ml-3 text-left whitespace-nowrap" sidebar-toggle-item>
    Routers
  </span>
  <svg
    sidebar-toggle-item
    class="w-6 h-6"
    fill="currentColor"
    viewBox="0 0 20 20"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      fill-rule="evenodd"
      d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
      clip-rule="evenodd"
    >
    </path>
  </svg>
</button>
<ul id="dropdown-layouts-router-api-config" class="hidden py-2 space-y-2">
  <li>
    <a
      href="/routers"
      class="flex items-center p-2 text-base text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700"
    >
      Router list
    </a>
  </li>
</ul>

(注:将原Phoenix模板中的<.link>转为标准HTML的<a>标签)

尝试过的JavaScript代码

document.addEventListener("DOMContentLoaded", function () {
    const dropdownBtn = document.getElementById("dropdownBtn");
    const dropdownMenu = document.getElementById("dropdownMenu");
    const chevron = document.getElementById("chevron");

    dropdownBtn.addEventListener("click", function (event) {
        event.stopPropagation(); // Prevent closing when clicking inside the dropdown
        dropdownMenu.classList.toggle("hidden");
        chevron.classList.toggle("rotate-180");
    });

    // Prevent dropdown from closing when clicking on items
    document.querySelectorAll("#dropdownMenu a").forEach(item => {
        item.addEventListener("click", function (event) {
            event.stopPropagation(); // Stop event from bubbling up
        });
    });

    // Close dropdown if clicked outside
    document.addEventListener("click", function () {
        dropdownMenu.classList.add("hidden");
        chevron.classList.remove("rotate-180");
    });
});

解决方案

方法一:使用Flowbite原生配置(推荐)

Flowbite的折叠组件支持通过ignoreClickOutsideClass配置忽略特定元素的点击事件,具体步骤:

  1. 修改HTML结构:给下拉菜单容器和菜单项添加自定义类(比如ignore-collapse-close)
<!-- 下拉菜单容器添加类 -->
<ul id="dropdown-layouts-router-api-config" class="hidden py-2 space-y-2 ignore-collapse-close">
  <li>
    <!-- 菜单项链接添加类 -->
    <a
      href="/routers"
      class="flex items-center p-2 text-base text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700 ignore-collapse-close"
    >
      Router list
    </a>
  </li>
</ul>
  1. 初始化Flowbite时配置忽略类:
document.addEventListener('DOMContentLoaded', function() {
  window.Flowbite.initCollapse({
    ignoreClickOutsideClass: 'ignore-collapse-close'
  });
});

这样点击带有ignore-collapse-close类的元素时,Flowbite不会触发折叠菜单的收起逻辑。

方法二:修正自定义JavaScript代码

原代码的问题在于元素ID不匹配(原HTML中没有dropdownBtn、dropdownMenu这些ID),同时需要避免与Flowbite的默认监听冲突,修改后代码:

document.addEventListener("DOMContentLoaded", function () {
    // 匹配实际HTML中的元素
    const dropdownBtn = document.querySelector('[data-collapse-toggle="dropdown-layouts-router-api-config"]');
    const dropdownMenu = document.getElementById("dropdown-layouts-router-api-config");
    const chevron = dropdownBtn.querySelector('svg[sidebar-toggle-item]:last-child');

    // 阻止Flowbite默认事件,接管折叠逻辑
    dropdownBtn.addEventListener("click", function (event) {
        event.stopImmediatePropagation();
        dropdownMenu.classList.toggle("hidden");
        chevron.classList.toggle("rotate-180");
    });

    // 点击菜单项时阻止事件冒泡,避免触发外部收起逻辑
    dropdownMenu.querySelectorAll("a").forEach(item => {
        item.addEventListener("click", function (event) {
            event.stopImmediatePropagation();
        });
    });

    // 点击外部区域时收起菜单
    document.addEventListener("click", function (event) {
        if (!dropdownBtn.contains(event.target) && !dropdownMenu.contains(event.target)) {
            dropdownMenu.classList.add("hidden");
            chevron.classList.remove("rotate-180");
        }
    });
});

注意:如果使用此方法,建议移除按钮上的data-collapse-toggle属性,避免与Flowbite的默认折叠逻辑冲突。

内容的提问来源于stack exchange,提问作者Mostafiz Ur Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:17:34