利用 Vue 3 + qrcode 打造通用二维码工具组件(生成 + 下载 + 扫码识别 + 摄像头扫码)

一、项目目标与应用场景

本文将封装一个功能全面的二维码工具组件,包含:

  • ✅ 文本转二维码
  • ✅ 下载二维码图片
  • ✅ 上传图片识别二维码
  • ✅ 支持颜色/尺寸配置
  • ✅ Base64/链接识别
  • ✅ 摄像头扫码识别(实时识别)

适用于后台管理、文档系统、支付系统、设备绑定等场景。

二、安装依赖 & 技术选型

主要技术栈如下:

安装:

npm install qrcode jsqr @zxing/library

三、项目结构(Mermaid)

graph TD
  A[QrCodeBox.vue] --> B[生成二维码区域]
  A --> C[上传图片识别]
  A --> D[摄像头扫码]
  B --> E[qrcode库生成Canvas]
  C --> F[jsQR识别图片]
  D --> G[@zxing读取摄像头流]

四、二维码工具组件封装(QrCodeBox.vue)

<template>
  <div class="qr-code-box">
    <input v-model="text" placeholder="请输入文本" />
    
    <div>
      <label>尺寸:</label>
      <input type="number" v-model="size" min="100" />
      <label>颜色:</label>
      <input type="color" v-model="color" />
    </div>

    <canvas ref="canvasRef"></canvas>
    <button @click="generate">生成二维码</button>
    <button @click="download">下载</button>

    <hr />

    <input type="file" accept="image/*" @change="onFileChange" />
    <p v-if="result">识别结果:{{ result }}</p>

    <hr />

    <div v-if="cameraSupported">
      <video ref="videoRef" autoplay muted playsinline width="200" />
      <button @click="startCamera">打开摄像头扫码</button>
      <button @click="stopCamera">关闭摄像头</button>
      <p v-if="liveResult">扫码结果:{{ liveResult }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import QRCode from 'qrcode'
import jsQR from 'jsqr'
import { BrowserMultiFormatReader } from '@zxing/library'

const text = ref('')
const size = ref(200)
const color = ref('#000000')
const canvasRef = ref(null)
const result = ref('')
const liveResult = ref('')
const videoRef = ref(null)
const codeReader = new BrowserMultiFormatReader()
let cameraRunning = false

const generate = async () => {
  if (!text.value) return
  await QRCode.toCanvas(canvasRef.value, text.value, {
    width: size.value,
    color: {
      dark: color.value,
      light: '#ffffff'
    }
  })
}

const download = () => {
  const canvas = canvasRef.value
  const link = document.createElement('a')
  link.download = 'qrcode.png'
  link.href = canvas.toDataURL('image/png')
  link.click()
}

const onFileChange = async (e) => {
  const file = e.target.files[0]
  if (!file) return
  const img = new Image()
  const reader = new FileReader()

  reader.onload = () => {
    img.src = reader.result
    img.onload = () => {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = img.width
      canvas.height = img.height
      ctx.drawImage(img, 0, 0)
      const imageData = ctx.getImageData(0, 0, img.width, img.height)
      const code = jsQR(imageData.data, img.width, img.height)
      result.value = code?.data || '未识别出二维码'
    }
  }

  reader.readAsDataURL(file)
}

const startCamera = async () => {
  if (cameraRunning) return
  try {
    cameraRunning = true
    const videoInputDevices = await codeReader.listVideoInputDevices()
    const selectedDeviceId = videoInputDevices[0]?.deviceId
    codeReader.decodeFromVideoDevice(selectedDeviceId, videoRef.value, (res, err) => {
      if (res) {
        liveResult.value = res.getText()
      }
    })
  } catch (e) {
    console.error('摄像头扫码失败', e)
  }
}

const stopCamera = () => {
  cameraRunning = false
  codeReader.reset()
}
onUnmounted(() => stopCamera())

const cameraSupported = 'mediaDevices' in navigator
</script>

<style scoped>
.qr-code-box {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
</style>

五、功能展示与优化建议

功能点状态
文本生成二维码✅ 支持
自定义颜色/大小✅ 支持
下载二维码图片✅ 支持
图片识别二维码✅ 支持
实时摄像头扫码✅ 支持
移动端适配✅ 支持
上传 Base64 链接✅ 可扩展(decode URI)

可扩展建议

  • 支持拖拽上传识别图片
  • 将组件抽离为 npm 包 / UI 插件
  • 加入二维码背景图、中心图标
  • 多语言支持

六、总结

通过整合 qrcodejsQR@zxing/library,我们实现了一个通用型二维码工具组件,适用于各类业务场景。无论是分享、扫码、登录、绑定设备,它都能帮你快速集成二维码功能。

后续可继续封装为 UI 库插件,或通过配置项拓展出多个二维码样式版本,提升组件复用性和灵活性。


到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值