如何让button_to点击事件冒泡至父元素?Stimulus.js场景适配
核心原因分析
你遇到的问题本质不是事件冒泡被阻止,而是button_to生成的同步表单提交会立即刷新页面,导致父div绑定的Stimulus eta#advance逻辑还没执行就被页面跳转中断了。以下是几种可行的解决方案:
方案1:将表单改为AJAX提交(推荐,改动最小)
通过Rails的UJS或Turbo将表单改为异步提交,避免页面刷新,让事件能正常冒泡执行。
修改button_to代码,添加remote: true(适配Rails UJS):
<%= button_to '2 Hours', set_eta_order_path(@order), method: :post, params: { ... }, remote: true %>
如果项目使用Turbo(Rails 7+默认),只需确保Turbo启用,它会自动处理异步提交,无需额外属性。
这样点击按钮后,表单会异步提交到服务器,页面保持加载状态,父div的click->eta#advance事件会正常触发,执行客户端跳转逻辑。
方案2:合并逻辑到Stimulus控制器(更可控)
放弃依赖事件冒泡,直接在Stimulus中监听表单提交事件,同时处理服务器提交和客户端跳转逻辑。
步骤1:修改HTML,给表单绑定Stimulus提交事件
<div data-controller="eta"> ... <div data-value="2hr"> <%= button_to '2 Hours', set_eta_order_path(@order), method: :post, params: { ... }, data: { action: "submit->eta#handleSubmit" } %> </div> ... </div>
步骤2:在Stimulus控制器中实现合并逻辑
import { Controller } from "@hotwired/stimulus" export default class extends Controller { handleSubmit(event) { // 阻止默认同步提交,改用AJAX event.preventDefault(); const form = event.target; const parentDiv = form.closest('[data-value]'); // 提交表单到服务器 fetch(form.action, { method: form.method, body: new FormData(form), headers: { 'Accept': 'application/json' } }) .then(response => { if (response.ok) { // 提交成功后执行原跳转逻辑 this.advance(parentDiv); } }) .catch(err => console.error('提交失败:', err)); } advance(element) { // 原有的页面跳转逻辑,直接传入目标元素获取值 const value = element.dataset.value; // ... 你的跳转代码逻辑 } }
这种方式逻辑更清晰,能确保只有在服务器提交成功后才执行客户端跳转,避免状态不一致。
方案3:手动触发父元素点击事件(临时应急方案)
如果必须保留同步表单提交,可在按钮点击时手动触发父div的点击事件,确保eta#advance逻辑执行。
修改button_to代码
<%= button_to '2 Hours', set_eta_order_path(@order), method: :post, params: { ... }, data: { action: "click->eta#triggerParent" } %>
在Stimulus控制器添加方法
triggerParent(event) { // 手动触发父div的click事件 event.currentTarget.closest('[data-action="click->eta#advance"]').click(); }
⚠️ 注意:同步提交会立即刷新页面,所以eta#advance中的逻辑必须是同步执行的,异步操作会被中断,体验较差,仅适合临时场景。
内容的提问来源于stack exchange,提问作者Marius Kressin
相关产品推荐
相关产品推荐

