uniapp中@tap和@click的区别

90 阅读3分钟

核心区别

  • 触发机制

    • @tap :基于触摸手势,轻触按下并短时间松开触发;避免移动端的 300ms 点击延迟。
    • @click :DOM 鼠标/指针点击事件,更偏 Web 语义,历史上在移动端可能存在 300ms 延迟。
  • 跨端兼容

    • @tap :跨平台统一,微信小程序/App/H5 都支持,映射到小程序的 bindtap 。
    • @click :在 H5/App WebView 环境可用;在小程序端不保证一致行为,部分场景不会触发或表现不稳。
  • 冒泡与阻止

    • @tap :可用 Vue 修饰符 .stop (在小程序中会转换为 catchtap ,阻止冒泡)、 .capture 等。
    • @click :按标准 DOM 事件处理修饰符;但在小程序端不一定生效。
  • 事件语义

    • @tap :移动优先手势;支持配套的 @longpress / @longtap 等。
    • @click :Web 点击语义;适合 PC/H5 的鼠标或键盘交互。 项目建议
  • 目标是微信小程序,统一使用 @tap 做交互绑定,保证跨端一致、响应更快。

  • 仅在纯 H5 页面且确需 DOM 点击语义时再考虑 @click 。

  • 需要阻止冒泡时,用 @tap.stop="handler" ;需要长按交互,用 @longpress="handler" 。

冒泡概念

  • 冒泡是事件在目标元素触发后,沿着层级从子节点向父节点、再向更高祖先节点依次触发相同事件)

  • 在小程序/uni-app中,触摸事件的冒泡对应 WeChat 的 bindtap 链路;阻止冒泡对应 catchtap 链路示意

  • 目标元素触发 → 直接父元素触发 → 祖先元素触发 → 页面根容器触发

  • 任何一个环节使用“阻止冒泡”,后续父级将不会再收到事件 在 uni-app 的写法

  • 正常冒泡:子和父都会触发

    <view class="parent" 
    @tap="onParentTap">
      <view class="child" 
      @tap="onChildTap"></view>
    </view>
    
  • 阻止冒泡:只触发子,不再传到父

    <view class="parent" 
    @tap="onParentTap">
      <view class="child" @tap.
      stop="onChildTap"></view>
    </view>
    
  • 捕获阶段优先(可选):父先于子触发

    <view class="parent" @tap.
    capture="onParentTap">
      <view class="child" 
      @tap="onChildTap"></view>
    </view>
    

与 @click 的关系

  • @tap 是触摸手势,跨端一致,避免移动端点击延迟,推荐在小程序使用

  • @click 是 Web DOM 点击;在小程序端不保证一致行为,冒泡也不如 @tap 可控 你当前页面的影响点

  • 底部栏 bottom-nav 中,图标是子元素,容器是父元素;若父容器以后绑定了 @tap ,图标的点击会冒泡到容器

  • 需要只触发图标自身行为时,在图标上使用 @tap.stop="handler" 即可避免父级收到事件

冒泡效果没有显示的原因

  • 父级没有监听:事件会“向上冒泡”,但只有父级绑定了同类型事件时你才会看到效果;

  • 事件类型不一致:父子必须同为 tap 链路;用 @click 的父级无法接收子级的 @tap 。

  • 被阻止传播:子级如果使用了 .stop 或在微信端使用了 catchtap ,父级不会收到。

  • 组件差异:某些内置组件的交互可能改变传播行为;在小程序里统一用 @tap 更稳。 怎么做

  • 给父容器绑定 @tap 以验证冒泡:

    <view class="bottom-nav" 
    @tap="onBottomNavTap">
      <button class="submitOrder" 
      @tap="submitOrder">下单</
      button>
    </view>
    

    在脚本里加:

    methods: {
      onBottomNavTap() { uni.
      showToast({ title'父容器收到 
      tap'icon'none' }) }
    }
    
  • 如果仍希望子级触发但不让父级触发,改用 @tap.stop :

    <button class="submitOrder" @tap.
    stop="submitOrder">下单</button>
    
  • 统一事件类型:确保父子都用 @tap ,不要父级 @click 子级 @tap 。