ByteNoteByteNote

字节笔记本

2026年7月19日

Vue.js 中 @click.stop 不生效的几种解决办法

API中转
¥120

Vue 里子元素加了 @click.stop,父元素的点击事件照样被触发了——这个问题我遇到过不止一次,下面把几种靠谱的解法记录一下。

问题复现

代码大概长这样:

html
<view class="pricetext" @click.prevent="goproductDetails(p)">
  参考价格<text class="jinqian">{{ formatAmount(p.price) }}</text>
  <u-icon style="margin-left: 15px" @click.stop="openEditPrice(p, item)" name="edit-pen" color="#2979ff" size="20"></u-icon>
  <text v-if="p.customPrice" class="custom-price">
    自定义价格<text class="jinqian">{{ formatAmount(p.customPrice) }}</text>
  </text>
</view>

外层 view 绑了点击跳转商品详情,里层的 u-icon 加了 .stop 想单独处理编辑价格。但实际跑起来,点图标的时候商品详情还是被打开了。

原因

大概率是组件内部的问题。u-icon 作为第三方组件,它渲染出来的实际 DOM 结构不一定是单个元素,.stop 只能阻止绑定元素上的冒泡,如果组件内部有多层包裹,事件从内部冒出来的时候就已经"逃"出 .stop 的控制范围了。

几种解决办法

方法一:给 icon 套一层原生容器(最省事)

在外面多包一个 view,把 .stop 放在这层容器上:

html
<view class="pricetext" @click.prevent="goproductDetails(p)">
  参考价格<text class="jinqian">{{ formatAmount(p.price) }}</text>
  <view @click.stop>
    <u-icon
      style="margin-left: 15px"
      @click="openEditPrice(p, item)"
      name="edit-pen"
      color="#2979ff"
      size="20"
    ></u-icon>
  </view>
  <text v-if="p.customPrice" class="custom-price">
    自定义价格<text class="jinqian">{{ formatAmount(p.customPrice) }}</text>
  </text>
</view>

这一层原生 view 是确定会直接渲染成 DOM 的,.stop 在它上面就能真正拦住冒泡。推荐这种写法。

方法二:在方法里手动 stopPropagation

$event 传到方法里手动阻止:

html
<u-icon
  style="margin-left: 15px"
  @click="handleIconClick($event, p, item)"
  name="edit-pen"
  color="#2979ff"
  size="20"
></u-icon>
js
methods: {
  handleIconClick(event, p, item) {
    event.stopPropagation()
    this.openEditPrice(p, item)
  }
}

和方法一思路一样,只不过把 .stop 从模板挪到了 JS 里。两种选一个就行。

方法三:uniapp 换用 @tap.stop

如果你用的是 uniapp(看代码里的 <view>u-icon 估计是),试试把 @click.stop 换成 @tap.stop

html
<u-icon
  style="margin-left: 15px"
  @tap.stop="openEditPrice(p, item)"
  name="edit-pen"
  color="#2979ff"
  size="20"
></u-icon>

uniapp 在小程序端有自己的事件机制,tapclick 的冒泡行为不一定完全一致,换了可能就好了。不过这个要看具体平台的表现,不保证百分百生效。

排查清单

如果上面三种都不行,检查这几个点:

  • 框架版本是否太旧,升级试试
  • 页面上有没有别的事件监听器(比如全局的、addEventListener 加的)在干扰
  • u-icon 组件本身有没有自定义的 $emit('click') 逻辑,内部重新 emit 出来的事件不会被外层的 .stop 拦住
分享: