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

Drupal 8 + Bootstrap 3:如何仅用自定义代码覆盖Collapse JS文件

不用拷贝整个Bootstrap Collapse.js,用自定义代码实现需求

当然可以不用拷贝整个Bootstrap collapse.js文件!你当前的做法虽然能实现功能,但最大的问题是将来Bootstrap版本更新时,你得手动同步整个文件的改动,维护成本很高。其实只需要利用Bootstrap Collapse内置的事件系统,编写少量自定义代码就能达到目的,完全不需要修改原插件代码。

步骤1:修改子主题的Libraries配置

首先打开你的bootstrap_subtheme_front_office.libraries.yml,移除掉你拷贝的bootstrap/js/collapse.js(父主题已经会加载这个文件),同时把你的自定义JS文件改名(比如改成custom-collapse.js,避免和原文件重名冲突),并确保你的自定义库依赖Bootstrap的collapse组件,让Drupal自动处理加载顺序:

global-styling:
  css:
    theme:
      fonts/font-awesome/css/font-awesome.css: {}
      # bootstrap/dist/css/bootstrap.css: {}
      # css/bootstrap-cosmo.css: {}
      css/style.css: {}
      # css/style-noel.css: {}
      # css/style-nouvel-an.css: {}
bootstrap-scripts:
  js:
    bootstrap/js/affix.js: {}
    bootstrap/js/alert.js: {}
    bootstrap/js/button.js: {}
    bootstrap/js/carousel.js: {}
    # 移除拷贝的Bootstrap collapse.js,依赖父主题的版本
    # bootstrap/js/collapse.js: {}
    bootstrap/js/modal.js: {}
    bootstrap/js/tooltip.js: {}
    bootstrap/js/popover.js: {}
    bootstrap/js/scrollspy.js: {}
    bootstrap/js/tab.js: {}
    bootstrap/js/transition.js: {}
    js/tour.js: {}
    # 使用改名后的自定义JS文件
    js/custom-collapse.js: {}
  dependencies:
    # 明确依赖Bootstrap的collapse组件,确保先加载原插件
    - bootstrap/collapse

步骤2:编写自定义JS代码

创建js/custom-collapse.js文件,把你优化后的代码放进去。这段代码通过监听Bootstrap Collapse的show.bs.collapse和hide.bs.collapse事件,实现菜单互斥切换和body类的添加/移除:

(function ($) {
  var $document = $(document);
  var $body = $(document.body);

  // 确保DOM加载完成后执行
  $document.ready(function () {
    // 定义选择器,方便后续维护
    var navbarCollapseFirst = '#navbar-collapse-first';
    var navbarCollapseSecond = '#navbar-collapse-second';
    var navbarCollapseBoth = navbarCollapseFirst + ',' + navbarCollapseSecond;

    // 缓存jQuery实例,提升性能
    var $navbarCollapseFirst = $(navbarCollapseFirst);
    var $navbarCollapseSecond = $(navbarCollapseSecond);

    // 跟踪当前展开的菜单
    var $open = $();

    $document
      // 监听任意菜单的展开事件
      .on('show.bs.collapse', navbarCollapseBoth, function (e) {
        $open = $(e.target);

        // 如果展开的不是第一个菜单,就关闭第一个
        if (!$navbarCollapseFirst.is($open)) {
          $navbarCollapseFirst.collapse('hide');
        }
        // 如果展开的不是第二个菜单,就关闭第二个
        else if (!$navbarCollapseSecond.is($open)) {
          $navbarCollapseSecond.collapse('hide');
        }

        // 添加body类
        $body.addClass('overlay-is-navbar-collapse');
      })
      // 监听任意菜单的收起事件
      .on('hide.bs.collapse', navbarCollapseBoth, function (e) {
        var $hide = $(e.target);

        // 更新当前展开的菜单状态
        if ($navbarCollapseFirst.is($hide) && $navbarCollapseFirst.is($open)) {
          $open = $();
        } else if ($navbarCollapseSecond.is($hide) && $navbarCollapseSecond.is($open)) {
          $open = $();
        }

        // 如果没有菜单展开,移除body类
        if (!$open[0]) {
          $body.removeClass('overlay-is-navbar-collapse');
        }
      });
  });
})(window.jQuery);

为什么这样可行?

Bootstrap的Collapse组件已经内置了一套事件系统,在菜单展开/收起的各个阶段都会触发对应的事件(比如show.bs.collapse是展开前触发,shown.bs.collapse是展开完成后触发)。我们只需要监听这些事件,然后插入自己的逻辑,完全不需要修改原插件的核心代码。

这种方式的好处:

  • 不需要维护整个Bootstrap JS文件,父主题更新Bootstrap时你的自定义代码不受影响
  • 代码更简洁,只关注你需要的自定义行为
  • 遵循了插件扩展的最佳实践,避免直接修改第三方库代码

内容的提问来源于stack exchange,提问作者3cfe5693

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:52:50