Ceiling

微信小程序开发避坑 - showActionSheet

调用 wx.showActionSheet 弹出操作菜单,代码写完真机一看:点了按钮什么都没发生,菜单根本没有弹出来。控制台也没有任何报错。排查到最后发现,原因仅仅是 itemList 传了 7 个选项。本文记录这个坑的现象、原因和几种解决方案。

一、问题现象

业务需要一个操作菜单,列出来刚好 7 个选项,于是直接传了进去:

wx.showActionSheet({
  itemList: ['编辑', '复制', '移动', '分享', '收藏', '下载', '删除'], // 7 项
  success (res) {
    console.log('选中了第', res.tapIndex, '项')
  }
})

运行结果:没有任何弹窗,也没有任何报错。点击按钮就像石沉大海,success 不触发,控制台干干净净。第一反应往往是去查按钮的绑定事件、数据绑定,绕一大圈才会怀疑到 showActionSheet 本身。

二、原因:itemList 最多只能 6 项

官方文档对 itemList 参数的说明很明确:

itemList:按钮的文字数组,数组长度最大为 6

也就是说 itemList 的合法长度是 1 ~ 6。传入 7 项时参数校验不通过,这次调用直接失败,弹窗自然不会出现。

更坑的是失败的方式:

  • 如果没写 fail 回调,这次失败就是完全静默的——不弹窗、不报错、不抛异常;
  • 用户点击按钮后取消(点了遮罩层),也会走 fail 回调,errMsgshowActionSheet:fail cancel,这属于正常现象而非错误。

所以排查这类「没反应」问题的第一步,永远是先把 fail 回调补上:

wx.showActionSheet({
  itemList: ['编辑', '复制', '移动', '分享', '收藏', '下载', '删除'],
  success (res) {
    console.log('选中了第', res.tapIndex, '项')
  },
  fail (err) {
    console.error('showActionSheet 失败:', err.errMsg)
  }
})

补上之后就能看到失败原因,而不是对着空气猜。

建议养成习惯:所有 wx. 异步 API 都挂上 fail 回调。小程序 API 参数非法时普遍是静默失败,没有 fail 回调就没有任何线索。

三、解决方案:自定义底部弹层

选项超过 6 个时,原生菜单就不够用了,可以自己实现一个底部弹层:遮罩层 + 固定在底部的列表,本质就是一个自定义组件。

<!-- components/action-sheet/index.wxml -->
<view wx:if="{{visible}}" class="mask" bindtap="close">
  <view class="sheet" catchtap="noop">
    <view
      wx:for="{{items}}"
      wx:key="index"
      class="sheet-item"
      data-index="{{index}}"
      bindtap="onTap">
      {{item}}
    </view>
  </view>
</view>
// components/action-sheet/index.js
Component({
  properties: {
    visible: Boolean,
    items: Array
  },
  methods: {
    onTap (e) {
      this.triggerEvent('select', { index: e.currentTarget.dataset.index })
      this.close()
    },
    close () {
      this.triggerEvent('close')
    },
    noop () {} // 拦截点击,防止冒泡关闭弹层
  }
})

这种方式不受数量限制,样式也完全可控,代价是要自己维护弹出动画、遮罩和安全区域适配。

四、避坑清单

  1. itemList 合法长度是 1 ~ 6,超出或传空数组都会导致调用失败、不弹窗。
  2. 参数非法是静默失败。没有 fail 回调就没有任何报错,这是这个坑最难排查的地方;给所有 wx. API 挂 fail 回调是基本功。
  3. 用户取消也走 failerrMsgshowActionSheet:fail cancel 属于正常交互,不要在 fail 里一律弹错误提示。
  4. success 回调里用 tapIndex 取选中项(从 0 开始),旧文档中的 index 字段已废弃。
  5. 菜单颜色用 itemColor 统一设置,不支持逐项设置颜色;需要逐项定制样式时只能走自定义弹层。

五、小结

  • wx.showActionSheetitemList 最多 6 项,传 7 项会静默失败,表现为「点了没反应」。
  • 排查「没反应」类问题的第一步是补 fail 回调,让失败显形。
  • 选项超限时,用自定义底部弹层替代原生菜单,不受数量限制且样式完全可控。