💡 一则也许对你有用的小广告 🏆

欢迎飞飞程序员   ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论

  • 正在进行中的项目:《FFBlog知识付费博客项目》 正在持续更新中,基于 Spring Boot 3.x + JDK 21...,[**点击查看**] ;
  • 《从零开发:FFBlog知识付费博客项目(全栈开发)》 演示链接: https://ffblog.ffcxy.com/  ;

截止目前, 飞飞  正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, Ai系统, CMS系统,在线商城系统,等等 ,欢迎点击围观

在 Vue 3 中生成二维码,最推荐使用的库是 qrcode

它是一个专门为 Vue 设计的组件,支持 Vue 3 的 Composition API,轻量且功能强大(支持自定义颜色、大小、甚至在二维码中间添加 Logo)。

以下是详细的保姆级教程:


1. 安装依赖

在你的 Vue 3 项目终端中运行:

Bash

npm install qrcode

2. 基础用法 (最简代码)

这是一个最简单的例子,展示如何将一个 URL 转换成二维码。

代码段

<template>
  <div class="qrcode-container">
    <qrcode-vue :value="qrValue" :size="200" level="H" />
    
    <p>扫描上方二维码登录</p>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import QrcodeVue from 'qrcode'

// 这里可以是后端返回的微信登录 URL
const qrValue = ref('https://www.ffcxy.com/')
</script>

3. 进阶用法:带 Logo 的二维码

在做“微信登录”或“APP下载”时,通常需要在二维码中间放一个小图标。

注意: 当中间有 Logo 时,一定要把 level (容错率) 设置为 'H' (High),否则二维码可能会因为遮挡而无法扫描。

代码段

<template>
  <div class="qrcode-card">
    <qrcode-vue
      :value="loginUrl"
      :size="300"
      level="H"
      :margin="2"
      :background="background"
      :foreground="foreground"
      :image-settings="imageSettings"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import QrcodeVue from 'qrcode'
import logoSrc from '@/assets/logo.png' // 确保你有这个图片

const loginUrl = ref('weixin://dl/login?uuid=abcdefg')
const background = ref('#ffffff') // 背景色
const foreground = ref('#000000') // 前景色

// 配置中间的 Logo
const imageSettings = ref({
  src: logoSrc,      // 图片路径
  width: 50,         // Logo 宽度
  height: 50,        // Logo 高度
  excavate: true,    // 是否镂空 (true 表示二维码中间会让出位置给 Logo,建议开启)
})
</script>

<style scoped>
.qrcode-card {
  padding: 20px;
  background: #f5f5f5;
  display: inline-block;
  border-radius: 8px;
}
</style>

4. 实战场景:结合后端动态生成

结合我们之前聊到的 “Redis + 轮询” 方案,完整的前端逻辑应该是这样的:

代码段

<template>
  <div class="login-box">
    <h3>微信扫码登录</h3>
    
    <div v-if="loading">正在获取二维码...</div>
    
    <div v-else class="qr-wrapper">
      <div :class="{ 'expired': isExpired }">
        <qrcode-vue :value="codeUrl" :size="200" level="H" />
      </div>
      
      <div v-if="isExpired" class="mask">
        <p>二维码已过期</p>
        <button @click="refreshCode">刷新</button>
      </div>
    </div>

    <p class="status-text">{{ statusMsg }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import QrcodeVue from 'qrcode'
import axios from 'axios' // 假设你用 axios

const codeUrl = ref('')      // 二维码内容
const loading = ref(true)    // 加载状态
const isExpired = ref(false) // 是否过期
const statusMsg = ref('请使用微信扫一扫')
let timer = null             // 轮询定时器

// 1. 获取登录 UUID 和 二维码内容
const getQrCode = async () => {
  loading.value = true
  isExpired.value = false
  try {
    // 请求后端接口:/api/login/create
    const res = await axios.get('/api/login/create') 
    // 假设后端返回 { uuid: 'xxx', url: 'weixin://...' }
    codeUrl.value = res.data.url 
    const uuid = res.data.uuid
    
    // 开始轮询状态
    startPolling(uuid)
  } catch (e) {
    statusMsg.value = "获取二维码失败"
  } finally {
    loading.value = false
  }
}

// 2. 轮询查状态
const startPolling = (uuid) => {
  // 先清除旧的定时器
  if(timer) clearInterval(timer)
  
  timer = setInterval(async () => {
    try {
      // 请求后端接口:/api/login/check?uuid=xxx
      const res = await axios.get(`/api/login/check?uuid=${uuid}`)
      const code = res.data.code
      
      if (code === 1) {
        statusMsg.value = "扫码成功,请在手机上确认"
      } else if (code === 2) {
        statusMsg.value = "登录成功!跳转中..."
        clearInterval(timer)
        // TODO: 跳转首页
      } else if (code === 3) {
        isExpired.value = true
        statusMsg.value = "二维码已过期"
        clearInterval(timer)
      }
    } catch (e) {
      console.error("轮询出错", e)
    }
  }, 2000) // 每2秒查一次
}

// 3. 刷新二维码
const refreshCode = () => {
  getQrCode()
}

// 组件挂载时获取
onMounted(() => {
  getQrCode()
})

// 组件销毁时清除定时器 (非常重要,防止内存泄漏)
onUnmounted(() => {
  if(timer) clearInterval(timer)
})
</script>

<style scoped>
.qr-wrapper {
  position: relative;
  width: 200px;
  height: 200px;
  margin: 0 auto;
}
.expired {
  opacity: 0.2; /* 过期变淡 */
}
.mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-weight: bold;
}
</style>

5. 参数详解表

属性名类型默认值说明
valuestring-必填,二维码的内容
sizenumber100宽度和高度 (px)
levelstring'L'容错率:'L' (低), 'M', 'Q', 'H' (高)。带 Logo 必须选 H
backgroundstring'#ffffff'背景色
foregroundstring'#000000'前景色 (二维码条纹颜色)
render-asstring'canvas'渲染模式:'canvas' 或 'svg'
image-settingsobject-配置中心 Logo (src, width, height, excavate)

总结

  • 简单生成:直接用 <qrcode-vue :value="..." />

  • 带 Logo:记得设置 :level="'H'":image-settings

  • 业务结合:利用 Vue 的响应式变量 (ref) 动态绑定 value,配合定时器轮询后端 Redis 状态。

上一篇 SpringBoot框架Lombok库中常用的注解详解和用法
下一篇 在使用tailwind布局时是使用grid布局还是使用flex布局

全部评论(0)

头像
😃 😁 😅 😂 😍 😜 😝 🤑 🥵 🥰 😙 😎 😵 😭 😱 😖 🥳 👽 🙈 🤡 😤 💣 💯 💢 ❤️ 👍 👏 👋 👌 🤏 🙏
还没有任何评论哟~