调用 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回调,errMsg为showActionSheet: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 () {} // 拦截点击,防止冒泡关闭弹层
}
})
这种方式不受数量限制,样式也完全可控,代价是要自己维护弹出动画、遮罩和安全区域适配。
四、避坑清单
itemList合法长度是 1 ~ 6,超出或传空数组都会导致调用失败、不弹窗。- 参数非法是静默失败。没有
fail回调就没有任何报错,这是这个坑最难排查的地方;给所有wx.API 挂fail回调是基本功。 - 用户取消也走
fail。errMsg为showActionSheet:fail cancel属于正常交互,不要在fail里一律弹错误提示。 success回调里用tapIndex取选中项(从 0 开始),旧文档中的index字段已废弃。- 菜单颜色用
itemColor统一设置,不支持逐项设置颜色;需要逐项定制样式时只能走自定义弹层。
五、小结
wx.showActionSheet的itemList最多 6 项,传 7 项会静默失败,表现为「点了没反应」。- 排查「没反应」类问题的第一步是补
fail回调,让失败显形。 - 选项超限时,用自定义底部弹层替代原生菜单,不受数量限制且样式完全可控。