# Tap事件

将用户在移动端手指按下后抬起、或在工具/PC端按下鼠标后抬起定义为一次 tap事件。tap事件基本上是基于 web 标准的 touch 事件做的封装。

# 点击态

为防止敏感接口被滥用,部分 API 触发时会检查并消耗点击态(如wx.openSetting、wx.requestSubscribeMessage),当点击态失效时,则对应功能会受到影响(调用失败或降级)。

每当用户点击时,相应 tap 事件的事件响应函数会获得点击态。除此之外,以下 API 的回调内也具有点击态:

  • wx.requestPayment 与 wx.requestOrderPayment,但这两个 API 获得的点击态不可用于触发 wx.openEmbeddedMiniProgram,详情可见支付后打开半屏小程序能力的相关调整通知
  • wx.showModal 与 wx.showActionSheet,点击态仅在 success 回调或接口调用成功后的 complete 中获取。

点击态只在当前事件响应函数所在的宏任务内有效。因此,setTimeout/setInterval 所包裹的函数不具备点击态,但 Promise/async/await 内有效。

由于 iOS 的 Promise 实现存在问题,小程序使用 polyfill 的 Promise。故 iOS 下使用 Promise/async/await 会失去点击态:

// <button bind:tap="handleTap">tap</button>
handleTap: async () => {
  // 点击态有效
  setTimeout(() => {
    // 失去点击态
  }, 100);
  Promise.resolve().then(() => {
    // Android 上具备点击态,iOS 上失去点击态
  });
};

在 tap 事件处理函数中进行异步请求是一个常见的行为。当 wx.request、wx.downloadFile 或 wx.getSetting 被调用时具有点击态,则会延续该点击态至 success/complete/fail 回调函数:

// <button bind:tap="handleTap">tap</button>
handleTap: async () => {
  // 点击态有效
  wx.request({
    url: "https://www.thissitedoesnotexist.com/step1",
    complete: () => {
      // 点击态有效
      wx.request({
        url: "https://www.thissitedoesnotexist.com/step2",
        complete: () => {
          // 点击态有效
        },
      });
    },
  });
};

单次 tap 生成的点击态被消耗之后,无法再延续点击态:

// <button bind:tap="handleTap">tap</button>
handleTap: async () => {
  // 点击态有效
  wx.openSettings({}); // 成功调用
  wx.request({
    url: "https://www.thissitedoesnotexist.com",
    complete: () => {
      // 失去点击态,因为点击态被 wx.openSettings 消耗掉了
    },
  });
  wx.openSettings({}); // 成功调用
};