news 2026/10/6 1:53:08

VueUse useQRCode 深度指南:在 Vue 3 中响应式生成二维码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
VueUse useQRCode 深度指南:在 Vue 3 中响应式生成二维码
  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载

useQRCode是 VueUse 生态中@vueuse/integrations包提供的集成函数,它把第三方二维码生成库qrcode包装成响应式组合式 API,让开发者可以用一行代码把任意文本变成 Base64 的 Data URL,并随源数据自动更新。本文以仓库中的 useQRCode 文档 为骨架,结合其 源码实现、演示组件 与包配置,完整讲解安装、用法、参数与底层原理,读完即可在 Vue 3 项目中直接落地使用。

背景:@vueuse/integrations 与 useQRCode 的定位

useQRCode属于 VueUse 的@vueuse/integrations子包。根据 integrations README,这个子包是 VueUse 的附加模块,专门为常用第三方工具库提供集成包装(integration wrapper),同一包内还包含useAxios、useCookies、useSortable等函数。useQRCode的本质是一个对qrcode库的响应式封装:底层生成二维码的算法与能力全部来自qrcode库,而 VueUse 负责把它接进 Vue 3 的响应式体系。

从 包导出声明 可以看到export * from './useQRCode',即useQRCode会随@vueuse/integrations主入口一并导出;同时 package.json 中单独配置了子路径导出"./useQRCode": "./dist/useQRCode.js",支持按需引入。

安装

qrcode是@vueuse/integrations的可选 peer dependency。查看 package.json 的peerDependencies与peerDependenciesMeta可知:qrcode: "^1.5"被标记为optional: true,意味着它不会随包自动安装,需要你手动补充。

npm i qrcode@^1

使用 pnpm 时则为:

pnpm add qrcode@^1

安装qrcode后,还需要确保项目中已有@vueuse/integrations本体:

npm i @vueuse/integrations

基本用法

useQRCode接受一个文本参数(字符串),返回一个保存着二维码 Data URL 的ShallowRef。最小示例:

import { useQRCode } from '@vueuse/integrations/useQRCode' // `qrcode` 是一个保存 data URL 字符串的 ref const qrcode = useQRCode('text-to-encode')

在模板中可以直接把返回的 ref 绑定到<img>的src上:

<img :src="qrcode" alt="QR Code" />

由于返回的是响应式 ref,二维码图片会随着 Data URL 的更新自动刷新,无需手动操作 DOM。

响应式用法:传入 ref / getter

useQRCode更实用的场景是传入一个ref或 getter 函数,此时生成的二维码会跟随源数据实时变化:

import { useQRCode } from '@vueuse/integrations/useQRCode' import { shallowRef } from 'vue' const text = shallowRef('text-to-encode') const qrcode = useQRCode(text)

配套模板即可实现"输入即刷新二维码"的交互:

<input v-model="text" type="text" /> <img :src="qrcode" alt="QR Code" />

用户每修改一次输入框内容,textref 变化,useQRCode内部侦听源值并重新调用底层生成逻辑,二维码图片立即更新。

完整可运行的官方 Demo

仓库中的 demo.vue 给出了带配置项的完整示例,其中指定了errorCorrectionLevel: 'H'(最高纠错等级)与margin: 3(留白边距):

<script setup lang="ts"> import { useQRCode } from '@vueuse/integrations/useQRCode' import { shallowRef } from 'vue' const text = shallowRef('https://vueuse.org') const qrcode = useQRCode(text, { errorCorrectionLevel: 'H', margin: 3, }) </script> <template> <note> Text content for QRCode </note> <input v-model="text" type="text"> <img v-if="text" class="mt-6 mb-2 rounded border" :src="qrcode" alt="QR Code"> </template>

v-if="text"的写法也提示了一个细节:当输入为空时,useQRCode不会生成二维码(详见下文源码分析),因此用条件渲染避免显示空图片。

options 配置参数说明

useQRCode的第二个参数options类型为QRCode.QRCodeToDataURLOptions,即直接透传给底层qrcode库toDataURL方法的配置对象。常用配置项包括:

参数含义说明
errorCorrectionLevel纠错等级取值为'L'、'M'、'Q'、'H','H'最高、生成的二维码最密集但容错最强(部分遮挡仍可扫描),默认通常为'M'
margin二维码四周留白宽度(模块数)官方 demo 使用3
width/height输出图片尺寸(像素)不传时由qrcode按版本与 scale 自动计算
scale每个模块的像素倍数控制放大倍率
color.dark/color.light前景色与背景色以十六进制字符串指定,例如{ dark: '#010599FF', light: '#FFBF60FF' }
type输出图片格式如'image/png'、'image/jpeg'、'image/webp',toDataURL默认输出 PNG Data URL

这些选项与qrcode库的toDataURLAPI 保持一致,所有具体取值与默认值均遵循底层库的行为;本文仓库证据为 demo 中对errorCorrectionLevel与margin的实际使用。

源码级原理剖析

来看 index.ts 的完整实现,整个函数只有 30 行左右,逻辑非常清晰:

import type { MaybeRefOrGetter } from 'vue' import { isClient, toRef } from '@vueuse/shared' import QRCode from 'qrcode' import { shallowRef, watch } from 'vue' export function useQRCode( text: MaybeRefOrGetter<string>, options?: QRCode.QRCodeToDataURLOptions, ) { const src = toRef(text) const result = shallowRef('') watch( src, async (value) => { if (src.value && isClient) result.value = await QRCode.toDataURL(value, options) }, { immediate: true }, ) return result }

核心机制可以拆成四点:

  1. 入参归一化:toRef(text)来自@vueuse/shared,把string | Ref<string> | () => string统一转换成Ref<string>。这就是为什么既可以传普通字符串、也可以传ref或 getter 函数。
  2. 响应式侦听:用watch侦听src,并设置{ immediate: true },使函数在调用瞬间就执行一次生成逻辑,首次拿到值即可渲染。
  3. 空值与 SSR 保护:if (src.value && isClient)保证两件事——源文本为空字符串时跳过生成;非浏览器环境(SSR)下不调用QRCode.toDataURL,避免服务端无 DOM 环境下执行不必要的计算。这也是为什么 demo 里要用v-if="text"兜底。
  4. 异步生成与浅层响应:底层QRCode.toDataURL返回 Promise,因此 watch 回调是async的;结果存入shallowRef(而不是ref),因为 Data URL 是字符串,不需要深层响应式代理,这样也避免了不必要的性能开销。

从调用链上看:useQRCode(text, options)→watch(src, async ...)→QRCode.toDataURL(value, options)→ 写入result。整个生成过程是异步的,赋值发生在 Promise resolve 之后,因此拿到返回值后图片的src需要绑定 ref 由 Vue 自动更新,而不是立即同步可用。

类型声明

文档与源码中导出的类型签名如下:

/** * Wrapper for qrcode. * * @param text * @param options */ export declare function useQRCode( text: MaybeRefOrGetter<string>, options?: QRCode.QRCodeToDataURLOptions, ): ShallowRef<string, string>

MaybeRefOrGetter<string>表示参数可以是普通字符串、Ref<string>或() => string三种形式;返回类型ShallowRef<string, string>明确告知调用方拿到的是一个只保存字符串的浅层 ref。TypeScript 用户无需额外类型定义,qrcode库的类型(@types/qrcode)会随推导自动生效,仓库的 devDependencies 中也包含@types/qrcode。

按需导入与 Tree-shaking 建议

useQRCode的压缩后体积记录在 export-size.json 中(约 306 B),非常轻量。为了获得更好的 tree-shaking 效果,integrations README 明确建议从子模块导入而非从主入口导入:

// 不推荐 import { useQRCode } from '@vueuse/integrations' // 推荐 import { useQRCode } from '@vueuse/integrations/useQRCode'

子路径导入之所以可行,正是因为 package.json 的exports字段单独声明了"./useQRCode": "./dist/useQRCode.js"这一映射,打包工具可以据此精确命中模块。

常见应用场景小结

  • 表单/链接生成器:用户输入 URL 或文本,实时预览二维码,官方 demo 即此场景;
  • 分享与支付码展示:把业务数据(如订单号、链接)编码为二维码图片直接渲染;
  • 需要统一样式的场景:通过color、width、margin等 options 控制二维码视觉输出。

需要留意的是:useQRCode生成的是 Data URL(Base64 图片),适合直接在<img :src>中渲染;若需要保存文件或上传图片,可基于 Data URL 进一步转成 Blob/File,但这不属于useQRCode本身的职责范围。

相关资源

  • 源码实现:packages/integrations/useQRCode/index.ts
  • 官方文档:packages/integrations/useQRCode/index.md
  • 官方演示:packages/integrations/useQRCode/demo.vue
  • 包导出与依赖配置:packages/integrations/package.json
  • 集成包函数清单:packages/integrations/README.md
  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载
上一篇:Devika项目中Playwright浏览器自动化问题的分析与解决方案
下一篇:AltStore完全指南:如何在未越狱iOS设备上实现应用自由?

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 1:49:33

DLSS Swapper 完整指南:3 步替换游戏内 DLSS 版本,随时可回退

DLSS Swapper 完整指南&#xff1a;3 步替换游戏内 DLSS 版本&#xff0c;随时可回退 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 游戏还卡在旧版 DLSS&#xff0c;新 DLL 早已释出&#xff0c;厂商却迟迟不出补丁。…

作者头像 李华
网站建设 2026/10/6 1:48:51

JavaScript 中比较两个 Date 对象的相等性与大小

文档教程知识库 【免费下载链接】til :memo: Today I Learned 项目地址&#xff1a; https://gitcode.com/gh_mirrors/ti/til 点击查看 免费下载 在 JavaScript 里判断两个 Date 对象是否相等并不是一个直观的操作——即使两个对象在概念上&#xff08;甚至打印出来&#xff0…

作者头像 李华
网站建设 2026/10/6 1:45:15

Packet Tracer校园网实战:VLAN间路由与NAT出网全配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:45:01

I2C远距离通信实战:TCA9517缓冲器与双绞线布局详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/6 1:45:01

PCIe硬件设计实战:从差分信号到链路训练全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华