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

Liferay 7.3.2 切换页面后aria-expanded固定为true导致下拉框无法关闭

问题根因

这是Bootstrap Collapse组件在Liferay局部页面切换场景下的典型冲突:

  • Liferay切换页面时默认走SPA局部渲染,首次加载时Bootstrap已经给所有data-toggle="collapse"的元素绑定了点击事件
  • 切换页面后旧DOM销毁但部分残留事件监听没有被清理,新加载的DOM又会被Bootstrap自动初始化绑定一次新的事件
  • 此时点击按钮会连续触发两次toggle操作:第一次把下拉从展开切为收起(触发collapsing类),第二次又立刻把下拉从收起切为展开,最终就呈现为无法关闭的现象,aria-expanded也会被第二次操作重置为true

解决方案

方案1:禁用当前元素的Bootstrap自动初始化,手动绑定事件

给按钮新增data-toggle="none"属性阻止自动初始化,然后手动写事件控制状态:

// Liferay 环境下可以写在 endNavigate 回调中保证页面渲染完成后执行
Liferay.on('endNavigate', () => {
  document.querySelectorAll('[data-target="#a_language_list"]').forEach(btn => {
    btn.addEventListener('click', () => {
      const target = document.querySelector(btn.dataset.target);
      if (target.classList.contains('open')) {
        target.classList.remove('open', 'show');
        btn.setAttribute('aria-expanded', 'false');
      } else {
        target.classList.add('open', 'show');
        btn.setAttribute('aria-expanded', 'true');
      }
    })
  })
})

方案2:页面切换时主动销毁旧的Collapse实例

在导航开始时清理残留的组件实例,导航结束后重新初始化:

Liferay.on('startNavigate', () => {
  document.querySelectorAll('[data-toggle="collapse"]').forEach(el => {
    const collapseInstance = bootstrap.Collapse.getInstance(el);
    if (collapseInstance) collapseInstance.dispose();
  })
})
Liferay.on('endNavigate', () => {
  document.querySelectorAll('[data-toggle="collapse"]').forEach(el => {
    new bootstrap.Collapse(el, {toggle: false})
  })
})

方案3:给组件ID加唯一命名空间

如果同一组件会在多个页面复用,要避免全局出现重复ID,Liferay 模板中可以用系统自带的命名空间前缀:

<#assign ns = fragmentEntryLinkNamespace />
<div id="${ns}a_language_selector">
    <button
        aria-controls="${ns}a_language_list"
        aria-expanded="false"
        role="button"
        data-toggle="collapse"
        data-target="#${ns}a_language_list"
    >
        <!-- CHANGE THIS -->
        <@liferay.language key="EN" />
    </button>

    <ul
        id="${ns}a_language_list"
        class="panel-collapse collapse"
        aria-labelledby="${ns}a_language_list"
    >
        <#if entries?has_content>
            <#list entries as navigationEntry>
                <li aria-label="${navigationEntry.getName()}">
                    <a href="${navigationEntry.getURL()}">
                        ${navigationEntry.getName()}
                    </a>
                </li>
            </#list>
        </#if>
    </ul>
</div>

内容的提问来源于stack exchange,提问作者Miska Rantala

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 07:39:01