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
相关产品推荐
相关产品推荐

