字
字节笔记本
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 在小程序端有自己的事件机制,tap 和 click 的冒泡行为不一定完全一致,换了可能就好了。不过这个要看具体平台的表现,不保证百分百生效。
排查清单
如果上面三种都不行,检查这几个点:
- 框架版本是否太旧,升级试试
- 页面上有没有别的事件监听器(比如全局的、
addEventListener加的)在干扰 u-icon组件本身有没有自定义的$emit('click')逻辑,内部重新 emit 出来的事件不会被外层的.stop拦住
分享: