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

Rails 7应用中返回按钮/菜单项点击时JavaScript无法运行求助

解决Rails 7 Turbo下个人资料页面JS仅全页刷新运行的问题

Rails 7默认使用Hotwire Turbo(原Turbolinks的升级版本),通过Turbo导航加载页面时,不会触发window.load这类完整页面刷新的事件,这就是你的JS仅在全页刷新时生效的核心原因。以下是针对性的解决方案:

核心修改思路

  1. 改用Turbo专属事件触发初始化逻辑
  2. 使用事件委托绑定交互事件,避免重复绑定且适配Turbo的页面替换机制
  3. 修复原代码中的语法错误

修改后的profile.js代码

// 监听Turbo页面渲染完成事件(Turbo导航或首次加载都会触发)
document.addEventListener('turbo:render', updateProfile);
// 兼容首次全页加载的场景
document.addEventListener('DOMContentLoaded', updateProfile);

function fileSelected() {
  const file = document.querySelector('#fileInput').files[0];
  if (!file) return;

  const reader = new FileReader();
  reader.onload = function(event) {
    document.querySelector('#profile-image').src = event.target.result;
  };
  reader.readAsDataURL(file);
}

function updateProfile() {
  // 用事件委托绑定输入验证事件(避免重复绑定)
  document.addEventListener('input', function(event) {
    if (event.target.id !== 'name') return;
    
    const errorElement = document.getElementById('error-message-name');
    const regex = /^.{3,}$/;
    const value = event.target.value;

    if (regex.test(value)) {
      errorElement.classList.remove("visible-error");
      errorElement.classList.add("invisible-error");
    } else {
      errorElement.classList.remove("invisible-error");
      errorElement.classList.add('visible-error');
    }
  }, { capture: true });

  // 用事件委托绑定切换按钮事件
  document.addEventListener('click', function(event) {
    if (event.target.id !== 'toggle') return;
    
    const toggleSwitch = event.target;
    if (toggleSwitch.getAttribute('data-type') === "influencer") {
      toggleSwitch.setAttribute('data-type', "vender");
      document.getElementById('profile_type').value = "vender";
    } else {
      toggleSwitch.setAttribute('data-type', "influencer");
      document.getElementById('profile_type').value = "influencer";
    }
  }, { capture: true });

  // 用事件委托绑定保存按钮事件
  document.addEventListener('click', function(event) {
    if (event.target.id !== 'save-button') return;
    
    const newName = document.getElementById('name').value;
    const newHeadline = document.getElementById('headline').value;
    const newCountry = document.getElementById('country').value;
    const newCity = document.getElementById('city').value;
    const newAbout = document.getElementById("about").value;
    const newProfileType = document.getElementById('toggle').getAttribute('data-type');
    const userId = document.getElementById('user_id').getAttribute('data');
    const fileInput = document.getElementById("fileInput");
    const file = fileInput.files[0];
    
    if (!file) {
      $.ajax({
        type: "PATCH",
        url: encodeURI(`/users/${userId}`),
        beforeSend: function(xhr) {
          xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
        },
        data: { 
          user: { 
            profile_type: newProfileType, 
            name: newName, 
            headline: newHeadline, 
            country: newCountry, 
            city: newCity, 
            about: newAbout 
          } 
        },
        success: function() {
          console.log("Update success.")
        }
      });
    } else {
      const formData = new FormData();
      formData.append("avatar", file);

      $.ajax({
        url: encodeURI(`/users/${userId}`),
        type: "PUT",
        beforeSend(xhr, options) {
          xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
          xhr.setRequestHeader('image-change', true);
          options.data = formData;
        },
        success: function() {
          console.log("Image Update success.")
        },
        error: () => {
          alert("An issue occured. Please try again.");
        }
      });
    }
  }, { capture: true });
}

关键说明

  1. Turbo事件替换:用turbo:render替代window.load,该事件在Turbo完成页面内容替换后触发,无论是首次加载还是Turbo导航都会执行初始化逻辑。
  2. 事件委托优势:将事件绑定到document而非单个元素,既避免了每次页面渲染重复绑定事件的问题,又能确保Turbo新渲染的元素能正常响应交互。
  3. 修复语法错误:原代码中regex.test(value)的value未定义,已改为event.target.value,确保验证逻辑正常运行。
  4. 无需强制刷新:移除了原代码中window.location.reload()的逻辑,保留Turbo的无刷新导航体验。

你的html.erb代码无需改动,data: { "turbolinks-track": "reload" }属性已经能正确跟踪JS文件的缓存更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:30:48