使用 qrcode.js 一行代码即可在前端生成当前 URL 的二维码:new QRCode("container-id", window.location.href),需确保脚本加载完成、DOM 就绪,并注意 canvas 像素密度、logo 覆盖及实例销毁等细节以保障跨端兼容性。

用 qrcode.js 一行代码生成页面当前 URL 的二维码
直接在 HTML 里引入轻量库就能跑,不用后端、不发请求。最常用的是 qrcode.js(注意不是 qrcode-generator 那个老版本),它支持 ES Module 和 script 标签两种加载方式。
常见错误现象:QRCode is not defined,多半是脚本没加载完就执行了初始化;或者用了 async 但没等 DOM 就调用 new QRCode(...)。
- 把
<script src="https://cdn.jsdelivr.net/npm/qrcode.js@1.5.3/dist/qrcode.min.js"></script>放在</body>前面 - 初始化时传入容器元素的
id,不要传错成 class 或 querySelector 字符串 - URL 默认是
window.location.href,如果只想扫到路径不含参数,得手动拼:location.origin + location.pathname - 移动端扫码经常失败?加
scale: 4参数提升清晰度,小屏设备默认 2 倍容易糊
QRCode.toCanvas() 导出为图片时 canvas 模糊或尺寸不对
浏览器默认 canvas 是 300×150 像素,哪怕你设了 CSS 宽高,实际绘制分辨率还是低。这不是 bug,是 canvas 渲染机制决定的。
使用场景:想让用户右键保存二维码图片,或者嵌进 PDF 生成流程里。
立即学习“前端免费学习笔记(深入)”;
- 先用
canvas.width = canvas.offsetWidth * window.devicePixelRatio手动提高像素密度 - 再调用
QRCode.toCanvas(canvas, url, { width: canvas.width }),width必须和 canvas 实际像素宽一致 - 导出 base64 时用
canvas.toDataURL('image/png', 1),第二个参数别省略,否则 Safari 可能降质 - 别在
DOMContentLoaded里立刻调toCanvas,确保 canvas 元素已渲染且尺寸稳定(可加setTimeout0 延迟或监听resize)
纯前端生成带 logo 的二维码,为什么中间图标总被裁掉或变模糊
qrcode.js 本身不支持 logo,得自己画。核心问题是 canvas 绘制顺序和坐标计算错位——logo 不是“贴上去”,而是“覆盖在二维码指定区域上”。
性能影响:每帧重绘 logo 会触发 canvas 重绘,但静态二维码只需一次。
- 先用
QRCode.toCanvas()生成基础码,再用ctx.drawImage(logoImg, x, y, width, height)覆盖中心 - logo 宽高建议不超过二维码总宽的 20%,否则纠错能力暴跌,微信/支付宝可能扫不出
- x/y 坐标不是简单除以 2,要算:
(canvas.width - logoWidth) / 2,且确保 logo 图片已加载完成(监听logoImg.onload) - 别用
img标签的width/height属性来算尺寸,要用自然宽高naturalWidth
Vue/React 项目里动态更新二维码内容,为什么旧码没销毁
重复 new QRCode() 不会自动清除前一个实例,DOM 里会残留多个 canvas,内存泄漏+显示错乱。
兼容性影响:Safari 下多次 init 同一容器,可能报 Cannot read property 'appendChild' of null。
- 每次生成前先检查是否已有实例:
if (window.qrCodeInstance) window.qrCodeInstance.clear() - 更稳妥的做法是销毁再重建:
window.qrCodeInstance?.remove()(v1.5.3+ 支持),然后赋新值 - React 函数组件里,用
useEffect的 cleanup 返回函数做清除;Vue 用onBeforeUnmount - 别把 QRCode 实例挂到全局
window上,优先用 ref 或 state 管理生命周期
真正麻烦的不是生成,是二维码在不同设备上的一致性——iOS 微信对 PNG 透明通道敏感,安卓部分浏览器 canvas 缩放插值算法差,这些没法靠一行代码解决。











