背景
2025年5月的晚风裹着槐花香,轻轻掀动窗帘的一角。办公室的灯光像散落在深海里的星星,零星亮着。我的电脑屏幕还泛着蓝光,我揉了揉发酸的眼睛,瞥见隔壁工位的妹子小语正对着屏幕叹气。
“又卡住了?”我端着半杯凉透的咖啡走过去。
小语抬起头,头发松松垮垮地挽在发顶,眼睛亮得像刚充完电的手机:“用户说活动二维码扫不出来,但后台显示数据正常……你看这图,中间的Logo放大后直接糊成一团,扫码器也不认。”
她指着屏幕上灰扑扑的二维码,像在抱怨一个不听话的孩子。
痛点:二维码的“感冒”时刻
小语的项目需要生成大量带品牌Logo的二维码,用于线下活动推广。起初用的是最简单的Canvas方案,但Logo一加,用户反馈“扫出来全是乱码”。后来改用SVG格式,结果在低端手机上加载卡顿,甚至导致页面崩溃。
“就像给二维码穿了件不合身的衣服,”小语苦笑着敲了敲键盘,“它自己难受,看的人也难受。”
我凑近看了看代码,发现数据请求倒是正常,问题全出在渲染环节——Logo覆盖破坏了二维码的容错率,而低配设备扛不住动态生成的计算量。
“之前是直接用原生qrcode
库生成Canvas,再用drawImage
把Logo贴上去。”小语调出历史代码,像展示一件失败的手工艺品,“但Logo太大时,遮住的模块太多,容错率就崩了。”
她指着一行注释:“试过限制Logo大小,但设计师觉得比例太小‘不够品牌感’。”
我点点头,想起上周组会时,前端大佬阿洛吐槽:“手动拼图就像拿针线补高铁轨道,不是不能用,是太容易翻车。”
启发时刻:茶水间的灵光
午夜茶水间里,阿洛捏着马克杯晃进来:“你们还在手动生成二维码?试试qrcode.vue
,人家连Logo留白都算好了。”
他掏出手机比划:“这个库内部会自动把Logo区域的模块预留出来,再用高容错模式(level='H')补全数据。就像织毛衣时留出纽扣孔,不用事后打补丁。”
我突然想起文档里那句“支持Reed-Solomon算法”,这不就是地铁票上那个能被刮花还能扫的纠错技术?
优化过程:温柔的代码手术
第二天,我帮小语换了方案:
pnpm add qrcode.vue
代码变成了这样:
<template>
<qrcode-vue
:value="qrText"
:size="200"
level="H"
:logo="{
src: '/logo.png',
logoSize: 0.2,
borderSize: 5,
bgColor: '#fff'
}"
/>
</template>
<script setup>
import { ref } from 'vue'
import QrcodeVue from 'qrcode.vue'
const qrText = ref('https://xxxxx.com')
</script>
“level='H'
能承受30%的损坏,”我边写边解释,“Logo控制在25%以内,加上白色背景缓冲,相当于给二维码戴了口罩——遮住脸,但不影响呼吸。”
小语眨眨眼:“那性能呢?”
“库内部做了防抖,数据更新时不会频繁重绘。大尺寸的话,用resizeObserver
动态加载。”我敲了敲键盘,“就像空调自动调温,不用人盯着。”
我还提醒她,logo 路径要放在 public
目录,确保访问稳定;如果二维码内容是动态的,比如后端接口返回链接,只要修改 qrText
绑定的值,二维码会自动刷新
后来,小语实测了一下页面加载时间,从原来卡顿的 300ms 降到了不到 100ms,体验明显流畅许多。她也遇到了一个小坑:初次加载时 logo 图片路径写错导致二维码显示异常,后来才意识到图片资源必须正确引用。
不过也踩了坑:
- 初版Logo用的是带透明通道的PNG,在部分安卓机上变成黑块。后来加了
bgColor
参数,像给图片加个素描框。 - 动态URL更新时偶尔闪白屏,加了
v-if
懒加载后缓解。
结局
小语关掉浏览器时,窗外的月光已经移到了工位边缘。她看着新生成的二维码,Logo恰到好处地嵌在中央,像枚精致的徽章。
渐渐地,办公室只剩下小语和我两盏灯。我眼睛望向窗外的星空,灯光下两人彼此的背影拉长,那一刻,工作不只是代码,更是默契和温柔的守护。