结论:用uqrcodejs,别碰原生qrcode.js或手写canvas——前者在小程序/App端报错,后者需三端适配;它自动路由平台渲染(小程序用canvas+uni.canvasToTempFilePath、H5用svg、App用native canvas),传对象即返tempFilePath或base64,直接绑定image src显示。直接上结论:用
uqrcodejs,别碰原生 qrcode.js 或手写 canvas 绘制逻辑——前者在小程序/App 端会报 canvas is not defined 或 cannot read property 'getContext' of null,后者要写三套平台适配代码,纯属自找麻烦。
为什么 uqrcodejs 是唯一靠谱选择
它不是简单封装,而是做了真正的平台路由:微信小程序 走 canvas + uni.canvastotempfilepath,h5 走 svg 渲染(不依赖 dom canvas),app 端(nvue) 用 native canvas 桥接。你传一个对象进去,它自动返回 tempfilepath(小程序/app)或 base64(h5),直接塞进 <image :src="qrcodeurl"></image> 就能显示。
- npm 安装命令必须是:
npm install uqrcodejs --save(注意包名是uqrcodejs,不是uQRCode或qrcode) - 导入必须写全后缀:
import uQRCode from 'uqrcodejs',不能用require,也不能漏掉.js(新版已改为 ES Module 导出) - 它不处理中文编码——若
text含中文,必须自己encodeURIComponent(),否则 H5 端扫码跳转会乱码
makeCode() 的 width 和 size 到底怎么设
很多人设了 width: 200 却发现二维码糊成一片、扫不出来,问题就出在没调 size。这两个参数完全不是一回事:
-
width:最终画布宽高(单位 px),决定图片尺寸,也影响导出文件大小 -
size:每个二维码“模块”(小方块)的像素大小,控制密度和清晰度;默认是4,对 200px 画布来说太小,模块挤在一起易误读 - 推荐组合:
width: 280+size: 6,容错率高、边缘锐利、长链接也能扫 - 别设
margin: 0——部分扫码器要求至少 4px 白边,否则识别失败
动态内容必须手动 JSON.stringify()
uqrcodejs 的 text 参数只认字符串,不自动序列化对象。如果你传的是 { uid: 123, channel: 'wechat' },它会直接 toString() 成 [object Object],生成的码扫出来就是这串字。
- 正确做法:
text: JSON.stringify({ uid: this.userId, channel: 'share' }) - 如果内容要带 URL 参数(比如分享页),先拼好完整 path:
text: encodeURIComponent('/pages/share/share?uid=' + this.userId) - 小程序「带 scene 的码」根本不能前端生成——那是微信服务端接口(
/wxa/getwxacodeunlimit)专属能力,前端只能请求后端返回的 base64 或云存储地址
生成时机必须卡在 $nextTick 或 onReady
常见错误是在 onLoad 里直接调 uQRCode.makeCode(),结果 canvas 元素还没挂载,插件内部取不到上下文,静默失败或报错。
- 小程序/H5:必须等页面真实渲染完成,用
this.$nextTick(() => { uQRCode.make(...) }) - 更稳妥写法是放在
onReady钩子,尤其当页面含条件渲染或异步数据时 - 如果 canvas 是通过
v-if控制显隐,确保v-if已为 true 再调用 - App 端(nvue)不支持普通 canvas,
uqrcodejs会自动 fallback 到 native 方案,但前提是项目已开启 nvue 编译模式且配置正确
errorCorrectLevel: 'H' 很好,但如果 text 过长(比如带 200 字符 token),即使 H 级也可能撑爆容量导致无法生成——这时候得先压缩内容(如用短链服务)或降级到 Q 级并加大 size,而不是硬扛。


















