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

Rails 6 / Turbolinks 5环境下turbolinks:load多次触发问题求助

问题根源

你的问题本质是事件监听重复叠加+Select2实例未正确清理两个原因共同导致的:

  1. 你当前的JS代码会被重复执行,每次执行都会给document新增一个turbolinks:load事件监听器,没有做去重处理。Turbolinks跳转页面时不会刷新整个JS运行环境,累加的监听器不会自动清除,跳转次数越多单次turbolinks:load触发时执行的初始化逻辑次数就越多,自然会生成多个Select2实例。
  2. 之前写的清理逻辑不完整:只删了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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:00:02