Rails 6 / Turbolinks 5环境下turbolinks:load多次触发问题求助
问题根源
你的问题本质是事件监听重复叠加+Select2实例未正确清理两个原因共同导致的:
- 你当前的JS代码会被重复执行,每次执行都会给
document新增一个turbolinks:load事件监听器,没有做去重处理。Turbolinks跳转页面时不会刷新整个JS运行环境,累加的监听器不会自动清除,跳转次数越多单次turbolinks:load触发时执行的初始化逻辑次数就越多,自然会生成多个Select2实例。 - 之前写的清理逻辑不完整:只删了Select2生成的DOM,没有销毁实例、解绑关联事件,也没有处理重复绑定的
turbolinks:load监听器本身。
解决方案
按以下步骤修改即可彻底解决:
1. 调整初始化逻辑,避免事件重复绑定
将你的初始化逻辑封装为独立函数,绑定监听器前先移除同名函数的绑定,从根源避免监听器叠加:
// 先移除已存在的监听,避免重复绑定 document.removeEventListener('turbolinks:load', initHomeSelect2); document.addEventListener('turbolinks:load', initHomeSelect2); function initHomeSelect2() { const $searchField = $('#home-search-field'); // 非首页/元素不存在时直接退出,减少无用执行 if (!$searchField.length) return; // 先销毁已存在的Select2实例、解绑旧事件 if ($searchField.data('select2')) { $searchField.off('select2:select'); $searchField.select2('destroy'); } // 初始化新实例 $searchField.select2({ selectionCssClass : 'home-select2-input' }); // 绑定选中跳转事件 $searchField.on('select2:select', function (e) { Turbolinks.visit(e.params.data.id); }); }
2. 修正Turbolinks缓存清理逻辑
在页面存入Turbolinks缓存前完整清理Select2相关内容,避免缓存携带冗余DOM和实例状态:
document.addEventListener('turbolinks:before-cache', function() { const $searchField = $('#home-search-field'); if ($searchField.data('select2')) { $searchField.off('select2:select'); $searchField.select2('destroy'); $('.select2-container').remove(); } });
3. 排查JS执行重复的根源
如果按上述修改后仍然有监听叠加问题,检查两个配置项:
- 不要把这段JS代码写在页面内联的
<script>标签里,统一放到Webpacker的app/javascript/packs目录下的全局JS文件中引入,避免Turbolinks跳转时重复执行内联代码 - 检查
application.js是否多次import了同一段Select2初始化代码,移除重复引入
内容的提问来源于stack exchange,提问作者Ruff9
相关产品推荐
相关产品推荐

