uni.scanCode 默认为一次性调用,连续扫码需在 success/fail 回调末尾用 setTimeout(..., 100) 延迟递归调用,避免原生相机资源未释放导致黑屏或闪退,且须分平台判断(H5 不支持)并做好失败兜底。

uni.scanCode 连续扫码时回调只触发一次?
默认情况下,uni.scanCode 是一次性调用:扫码成功或失败后就结束,不会自动重启扫描界面。所谓“连续扫码”,本质是手动控制「关闭后立刻重新打开」,而不是靠 API 自带循环能力。
常见错误现象:uni.scanCode 调用后扫完一个码,页面停留在扫码结果页,不返回摄像头界面;或者在 success 回调里直接再次调用 uni.scanCode,但部分安卓机型会卡死、黑屏或报错 scanCode:fail system error。
- 必须在
success或fail回调末尾手动调用下一次uni.scanCode - 不能在
success中同步立即再调,需加setTimeout(..., 0)或nextTick(Vue 项目)释放当前执行栈 - H5 端不支持
uni.scanCode,需提前判断平台:uni.getSystemInfoSync().platform !== 'h5'
如何安全地实现「扫完一个马上继续扫」
核心思路:用递归式调用 + 异步调度,避免阻塞原生扫码模块的资源释放。尤其在 App 端(iOS/Android),原生层需要时间回收摄像头实例。
示例代码(Vue 3 setup 语法):
const startScan = () => {
uni.scanCode({
success: (res) => {
console.log('扫码结果', res.result)
// ✅ 处理你的业务逻辑(如提交、跳转、校验等)
// ❌ 不要在这里直接调用 uni.scanCode()
// ✅ 延迟触发下一次扫码,让原生层释放资源
setTimeout(() => {
startScan()
}, 100)
},
fail: (err) => {
console.warn('扫码失败', err)
// 可选:失败后是否继续?根据需求决定
// setTimeout(() => { startScan() }, 300)
}
})
}
// 首次启动
startScan()
- 延迟时间建议 100–300ms:太短(如 0)在某些 Android 机型上仍可能冲突;太长(如 1000ms)影响体验
- 务必在
fail中做兜底处理,否则用户点取消或权限拒绝后流程就中断了 - 若需「手动退出连续扫码」,加个开关变量(如
isScanning.value = false),在回调里判断是否继续
App 端连续扫码闪退 / 黑屏的真正原因
不是代码写错了,而是原生扫码组件未完全销毁就重建。uni-app 的 uni.scanCode 底层复用了系统相机 Activity(Android)或 ViewController(iOS),频繁创建销毁容易触发资源竞争。
- 真机测试必须覆盖主流 Android 厂商(华为、小米、OPPO)——它们对相机管理更激进,容易 kill 掉未释放的预览 Surface
- 避免在
onShow或onPullDownRefresh等高频钩子中无条件调用startScan - 如果业务允许,可改用
uni.chooseImage({ sourceType: ['album', 'camera'] })拍照后用第三方库(如 jsQR)前端解析二维码,绕过原生扫码限制(适合低频、非强实时场景)
微信小程序里能连续扫码吗?
可以,但机制不同:wx.scanCode 支持 onlyFromCamera: true 和 scanType: ['qrCode', 'barCode'],且微信自身扫码界面自带「继续扫描」按钮。uni-app 编译到微信小程序时,uni.scanCode 就是透传给 wx.scanCode 的。
不过要注意:
- 微信基础库 2.24.0+ 才支持扫码后自动回到摄像头(旧版仍需手动调用)
- 必须配置
"mp-weixin": { "permission": { "scope.camera": { "desc": "用于扫码" } } }到manifest.json,否则首次扫码会静默失败 - 微信端无法通过 JS 控制「是否显示右上角关闭按钮」或「是否禁用相册选择」,这些由微信 UI 决定
连续扫码这事,关键不在“怎么写”,而在于理解每个平台的原生限制和释放节奏。别迷信“一次调用无限循环”,老老实实加 delay、做状态控制、分平台兜底,比任何黑科技都管用。


















