简介
在 web 应用中,生成二维码是常见的需求。本文介绍如何用 vue3 和 typescript 开发一个二维码生成组件,支持生成图片或 canvas 形式的二维码,并提供丰富的配置选项。
技术栈
- vue3
- typescript
- element plus
- qrcode
组件功能
- 支持生成图片和 canvas 形式的二维码: 可以根据需求选择生成图片或 canvas 形式的二维码。
- 自定义配置选项: 提供丰富的配置选项,如二维码大小、图标大小、二维码颜色、容错级别等。
- 支持lgog二维码: canvas 形式下支持配置logo二维码。
- 二维码预览: 图片形式下支持二维码预览功能。
- 下载: 组件内提供下载二维码到本地的方法。
组件代码
生成uuid
方法,防止在 canvas 形式下同一页面生成多个二维码时导致 canvasid
重复
/** * @description 生成唯一 uuid * @return string */ export function generateuuid() { if (typeof crypto === "object") { if (typeof crypto.randomuuid === "function") { return crypto.randomuuid(); } if (typeof crypto.getrandomvalues === "function" && typeof uint8array === "function") { const callback = (c: any) => { const num = number(c); return (num ^ (crypto.getrandomvalues(new uint8array(1))[0] & (15 >> (num / 4)))).tostring(16); }; return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, callback); } } let timestamp = new date().gettime(); let performancenow = (typeof performance !== "undefined" && performance.now && performance.now() * 1000) || 0; return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => { let random = math.random() * 16; if (timestamp > 0) { random = (timestamp + random) % 16 | 0; timestamp = math.floor(timestamp / 16); } else { random = (performancenow + random) % 16 | 0; performancenow = math.floor(performancenow / 16); } return (c === "x" ? random : (random & 0x3) | 0x8).tostring(16); }); }
以下是组件的核心代码:
<script setup lang="ts"> import { ref, onmounted, computed } from "vue"; import qrcode, { type qrcoderenderersoptions } from "qrcode"; import { generateuuid } from "@/utils/util"; interface qrcodeprops { type?: "canvas" | "img"; // 二维码类型 ==> 默认img, img 支持预览,canvas支持logo size?: number; // 二维码大小 ==> 默认200 iconsize?: number; // 二维码图标大小 ==> 默认40 content: string; // 二维码内容 ==> 必填 logo?: string; // 二维码logo ==> 默认无 options?: qrcoderenderersoptions; // 二维码配置 ==> 默认无 errorlevel?: "l" | "m" | "q" | "h"; // 二维码容错级别 ==> 默认h } // 接收父组件参数并设置默认值 const props = withdefaults(defineprops<qrcodeprops>(), { type: "img", size: 200, iconsize: 40, errorlevel: "h" }); const qrcodeurl = ref<string>(""); const canvasid = ref("canvas" + generateuuid()); const loading = ref(true); const qrcodestyle = computed(() => { return { width: props.size + "px", height: props.size + "px" }; }); // 生成二维码 const initqrcode = async () => { if (props.type === "canvas") { const canvasref: any = await qrcode.tocanvas(document.getelementbyid(canvasid.value), props.content, { width: props.size, margin: 2, errorcorrectionlevel: props.errorlevel, ...props.options }); if (props.logo) { const ctx = canvasref.getcontext("2d"); const iconbgw = props.iconsize + 5; const iconbgh = props.iconsize + 5; const iconbgx = (canvasref.width - iconbgw) / 2; const iconbgy = (canvasref.width - iconbgh) / 2; ctx.fillstyle = "#fff"; ctx.fillrect(iconbgx, iconbgy, iconbgw, iconbgh); // logo const iconx = (canvasref.width - props.iconsize) / 2; const icony = (canvasref.width - props.iconsize) / 2; const image = new image(); image.crossorigin = "anonymous"; // 设置图片的跨域属性 image.onload = () => { ctx.drawimage(image, iconx, icony, props.iconsize, props.iconsize); qrcodeurl.value = canvasref.todataurl(); }; image.src = props.logo; } else { qrcodeurl.value = canvasref.todataurl(); } loading.value = false; } else { const url = await qrcode.todataurl(props.content, { width: props.size, margin: 2, errorcorrectionlevel: props.errorlevel, ...props.options }); qrcodeurl.value = url; loading.value = false; } }; // 下载二维码 const downloadqrcode = (filename: string = generateuuid(), filetype: string = ".png") => { const exportfile = document.createelement("a"); exportfile.style.display = "none"; exportfile.download = `${filename}${filetype}`; exportfile.href = qrcodeurl.value; document.body.appendchild(exportfile); exportfile.click(); // 去除下载对 url 的影响 document.body.removechild(exportfile); }; onmounted(() => { initqrcode(); }); defineexpose({ downloadqrcode }); </script> <template> <div :style="qrcodestyle" overflow-hidden rounded-lg border border-slate-300 border-solid v-loading="loading"> <imagepreview :width="qrcodestyle.width" :height="qrcodestyle.height" v-if="type === 'img'" :image-url="qrcodeurl" /> <canvas v-else :style="qrcodestyle" :id="canvasid"></canvas> </div> </template> <style lang="scss" scoped></style>
总结
通过结合 vue3、typescript 和其他现代前端技术,我们打造了一个功能丰富的二维码生成组件。该组件支持多种形式展示,包括图片和 canvas 二维码。用户可以轻松放大预览图片二维码,或者通过 canvas 添加自定义 logo。除此之外,在组件内还提供了便捷的下载功能。这一解决方案为开发者在 web 应用中集成二维码生成功能提供了便捷而强大的工具。
希望这篇文章能够帮助你更好地了解如何使用 vue3 和 typescript 实现 生成二维码功能!如果你有任何问题或建议,请随时提出。
以上就是vue3+typescript实现二维码生成组件的详细内容,更多关于vue3+typescript二维码的资料请关注代码网其它相关文章!
发表评论