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

Rails 7中Turbo替代Stimulus后嵌套点击交互失效问题求助

核心问题是HTML规范不允许<a>标签(由link_to生成)嵌套<button>标签(由button_to生成),浏览器会自动修正这种非法嵌套结构,直接导致内层button的点击事件被外层link的跳转行为覆盖,调整z-index根本解决不了这个问题。

下面给你几个可行的解决思路:


方案一:用Stimulus + Turbo Streams发起POST请求(推荐,保持原布局结构)

放弃button_to,回到Stimulus控制器,通过Turbo发起POST请求,既避免非法嵌套,又保留原有的叠加布局:

  1. 重构局部视图_overlay_element.html.erb:
<svg 
    id="overlay-element"
    data-controller="overlay"
    data-action="click->overlay#triggerOverlayAction"
    data-example-id="<%= example.id %>"
    fill="red" 
    viewBox="0 0 24 24" 
    stroke-width="1.5" 
    stroke="currentColor" 
>
    <path d="M11..."/>
</svg>
  1. 更新Stimulus控制器overlay_controller.js,用Turbo发起POST请求:
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  triggerOverlayAction(event) {
    // 阻止事件冒泡,避免触发外层link_to的跳转
    event.stopPropagation();
    
    const exampleId = this.element.dataset.exampleId;
    const url = `/overlay?example_id=${exampleId}`; // 对应你的overlay_path

    // 用Turbo发起POST请求
    Turbo.fetch(url, {
      method: "POST",
      headers: {
        "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content,
        "Accept": "text/vnd.turbo-stream.html"
      }
    });
  }
}
  1. 原视图代码保持不变:
<%= link_to example_path(@example), id: 'example-element' do %>
    <%= image_tag @example.image %>
    <%= render 'layouts/overlay_element', example: @example %>
<% end %>

方案二:拆分布局,避免嵌套(更符合HTML规范)

把link_to和按钮放在同一层级,用CSS绝对定位让svg叠加在图片上方:

  1. 原视图代码调整:
<div class="example-container">
  <%= link_to example_path(@example), id: 'example-element' do %>
    <%= image_tag @example.image %>
  <% end %>
  
  <%= render 'layouts/overlay_element', example: @example %>
</div>
  1. 局部视图_overlay_element.html.erb(用button_to没问题,因为不再嵌套):
<%= button_to overlay_path(example_id: example.id), method: :post, class: 'overlay-button' do %>
  <svg 
      id="overlay-element"
      fill="red" 
      viewBox="0 0 24 24" 
      stroke-width="1.5" 
      stroke="currentColor" 
  >
      <path d="M11..."/>
  </svg>
<% end %>
  1. 添加CSS样式实现叠加:
.example-container {
  position: relative;
  display: inline-block; /* 让容器适应图片大小 */
}

.overlay-button {
  position: absolute;
  top: 0;
  right: 0; /* 调整位置到你需要的地方 */
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
}

用link_to配合Turbo的data-turbo-method属性代替button_to,这样生成的还是<a>标签,不会出现嵌套问题:

局部视图_overlay_element.html.erb修改为:

<%= link_to overlay_path(example_id: example.id), 
            data: { turbo_method: :post }, 
            class: 'overlay-link' do %>
  <svg 
      id="overlay-element"
      fill="red" 
      viewBox="0 0 24 24" 
      stroke-width="1.5" 
      stroke="currentColor" 
  >
      <path d="M11..."/>
  </svg>
<% end %>

然后给.overlay-link加CSS去掉默认链接样式:

.overlay-link {
  text-decoration: none;
  color: inherit;
  display: inline-block;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 23:25:59