#@veaba/qrcode-js
纯 JavaScript 实现的 QRCode 生成库,无需 WASM,兼容性更好,适合对 WASM 有顾虑的场景。
#安装
npm install @veaba/qrcode-js#与 WASM 版本的区别
| 特性 | @veaba/qrcode-js | @veaba/qrcode-wasm |
|---|---|---|
| 依赖 | 无 | 需要加载 .wasm 文件 |
| 兼容性 | IE11+ | 现代浏览器 |
| 性能 | 快 | 更快 |
| 包大小 | ~15KB | ~45KB (含 wasm) |
| 启动时间 | 即时 | 需要异步初始化 |
| API | 统一 | 统一 |
#基础使用
#创建 QRCode
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
// 创建 QRCode 实例(构造函数直接传入文本)
const qr = new QRCodeCore('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 获取 SVG
const svg = qr.toSVG(256);
document.getElementById('qrcode').innerHTML = svg;#指定尺寸
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
const qr = new QRCodeCore('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 生成 512x512 的 SVG
const svg = qr.toSVG(512);#使用缓存(推荐)
对于重复文本,使用缓存版本可大幅提升性能:
import {
generateRoundedQRCodeCached,
clearQRCodeCache,
getCacheStats
} from '@veaba/qrcode-js';
// 第一次生成会缓存
const svg1 = generateRoundedQRCodeCached('https://example.com', 256, 8);
// 第二次生成直接从缓存读取,速度提升 10 倍+
const svg2 = generateRoundedQRCodeCached('https://example.com', 256, 8);
// 查看缓存状态
console.log(getCacheStats()); // { size: 1, maxSize: 100, keys: [...] }
// 清空缓存
clearQRCodeCache();#样式化 QRCode
#基础样式
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
const qr = new QRCodeCore('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 样式化 SVG
const styledSvg = qr.toStyledSVG({
size: 256,
colorDark: '#000000',
colorLight: '#ffffff',
borderRadius: 8,
quietZone: 2,
});#渐变 QRCode
const gradientSvg = qr.toStyledSVG({
size: 256,
gradient: {
color1: '#667eea',
color2: '#764ba2',
},
quietZone: 2,
});#圆角 QRCode
const roundedSvg = qr.toStyledSVG({
size: 256,
borderRadius: 12, // 圆角半径
quietZone: 2,
});#带 Logo 区域
const logoSvg = qr.toStyledSVG({
size: 256,
quietZone: 2,
logoRegions: [
{ row: 8, col: 8, size: 5 }, // 中心 5x5 区域留白
],
});#预设样式函数
import {
generateRoundedQRCode,
generateGradientQRCode,
generateQRCodeWithLogoArea,
generateWechatStyleQRCode,
generateDouyinStyleQRCode,
generateAlipayStyleQRCode,
generateXiaohongshuStyleQRCode,
generateCyberpunkStyleQRCode,
generateRetroStyleQRCode,
generateMinimalStyleQRCode,
} from '@veaba/qrcode-js';
// 圆角
const svg1 = generateRoundedQRCode('https://github.com/veaba/qrcodes', 256, 8);
// 渐变
const svg2 = generateGradientQRCode('https://github.com/veaba/qrcodes', 256, '#667eea', '#764ba2');
// Logo 区域
const svg3 = generateQRCodeWithLogoArea('https://github.com/veaba/qrcodes', 256, 0.2);
// 微信风格
const svg4 = generateWechatStyleQRCode('https://weixin.qq.com', 256);
// 抖音风格
const svg5 = generateDouyinStyleQRCode('https://douyin.com', 256);#批量生成
import { generateBatchQRCodes, generateBatchQRCodesCached } from '@veaba/qrcode-js';
const texts = [
'https://github.com/veaba/qrcodes/1',
'https://github.com/veaba/qrcodes/2',
'https://github.com/veaba/qrcodes/3',
];
// 批量生成
const svgs = generateBatchQRCodes(texts, { size: 256 });
// 缓存版本
const svgsCached = generateBatchQRCodesCached(texts, { size: 256 });#异步生成
import { generateQRCodeAsync, generateBatchAsync } from '@veaba/qrcode-js';
// 单个异步生成
const result = await generateQRCodeAsync('https://example.com', {
size: 256,
cache: true
});
console.log(result.svg);
// 批量异步生成
const results = await generateBatchAsync(texts, {
size: 256,
cache: true
});#获取模块数据
如果需要自定义渲染:
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
const qr = new QRCodeCore('https://github.com/veaba/qrcodes', QRErrorCorrectLevel.H);
// 获取模块数量
const count = qr.getModuleCount();
console.log(count); // 例如:25(Version 2)
// 检查某个位置是否为深色
for (let row = 0; row < count; row++) {
for (let col = 0; col < count; col++) {
if (qr.isDark(row, col)) {
// 渲染深色模块
}
}
}#在框架中使用
#React
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
import { useMemo } from 'react';
function QRCodeComponent({ text, size = 256 }) {
const svg = useMemo(() => {
const qr = new QRCodeCore(text, QRErrorCorrectLevel.H);
return qr.toSVG(size);
}, [text, size]);
return <div dangerouslySetInnerHTML={{ __html: svg }} />;
}#Vue
<template>
<div v-html="svg" />
</template>
<script setup>
import { QRCodeCore, QRErrorCorrectLevel } from '@veaba/qrcode-js';
import { computed } from 'vue';
const props = defineProps({
text: String,
size: { type: Number, default: 256 },
});
const svg = computed(() => {
const qr = new QRCodeCore(props.text, QRErrorCorrectLevel.H);
return qr.toSVG(props.size);
});
</script>#性能对比
与 WASM 版本的性能对比(ops/s):
| 测试项 | @veaba/qrcode-js | @veaba/qrcode-wasm |
|---|---|---|
| 单条生成 (medium) | 9,662 | ~15,000 |
| SVG 输出 | 9,827 | ~17,000 |
| 缓存命中 | ~500,000 | ~500,000 |
虽然 WASM 更快,但纯 JS 版本在大多数场景下性能足够,且无需处理异步初始化的复杂性。
#何时选择 @veaba/qrcode-js?
选择 @veaba/qrcode-js 而不是 @veaba/qrcode-wasm 的场景:
- ✅ 需要支持 IE11 等旧浏览器
- ✅ 对包大小敏感(JS 版本更小)
- ✅ 不想处理 WASM 的异步初始化
- ✅ 生成频率不高,性能不是瓶颈
- ✅ 内容安全策略(CSP)限制 WASM
选择 @veaba/qrcode-wasm 的场景:
- ✅ 追求极致性能
- ✅ 高频批量生成
- ✅ 现代浏览器环境
#API 统一性
@veaba/qrcode-js 和 @veaba/qrcode-wasm 提供完全一致的 API:
// 两个包的 API 完全相同
import { QRCodeCore, generateRoundedQRCodeCached } from '@veaba/qrcode-js';
// 或
import init, { QRCodeCore, generateRoundedQRCodeCached } from '@veaba/qrcode-wasm';
await init();
// 以下代码在两个包中完全相同
const qr = new QRCodeCore('text', QRErrorCorrectLevel.H);
const svg = qr.toSVG(256);
const styledSvg = generateRoundedQRCodeCached('text', 256, 8);这使得在两个包之间切换变得非常容易,只需更改导入语句即可。