💡 一则也许对你有用的小广告 🏆
欢迎飞飞程序员 ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 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. 参数详解表
| 属性名 | 类型 | 默认值 | 说明 |
| value | string | - | 必填,二维码的内容 |
| size | number | 100 | 宽度和高度 (px) |
| level | string | 'L' | 容错率:'L' (低), 'M', 'Q', 'H' (高)。带 Logo 必须选 H |
| background | string | '#ffffff' | 背景色 |
| foreground | string | '#000000' | 前景色 (二维码条纹颜色) |
| render-as | string | 'canvas' | 渲染模式:'canvas' 或 'svg' |
| image-settings | object | - | 配置中心 Logo (src, width, height, excavate) |
总结
简单生成:直接用 <qrcode-vue :value="..." />。
带 Logo:记得设置 :level="'H'" 和 :image-settings。
业务结合:利用 Vue 的响应式变量 (ref) 动态绑定 value,配合定时器轮询后端 Redis 状态。