最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3+TypeScript實現(xiàn)二維碼生成組件

 更新時間:2024年04月28日 09:12:03   作者:下雨會打傘的前端  
在?Web?應用中,生成二維碼是常見的需求,本文介紹如何用?Vue3?和?TypeScript?開發(fā)一個二維碼生成組件,支持生成圖片或?canvas?形式的二維碼,并提供豐富的配置選項,感興趣的小伙伴跟著小編一起來看看吧

簡介

在 Web 應用中,生成二維碼是常見的需求。本文介紹如何用 Vue3 和 TypeScript 開發(fā)一個二維碼生成組件,支持生成圖片或 canvas 形式的二維碼,并提供豐富的配置選項。

技術棧

組件功能

  • 支持生成圖片和 canvas 形式的二維碼: 可以根據(jù)需求選擇生成圖片或 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
}

// 接收父組件參數(shù)并設置默認值
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 和其他現(xiàn)代前端技術,我們打造了一個功能豐富的二維碼生成組件。該組件支持多種形式展示,包括圖片和 canvas 二維碼。用戶可以輕松放大預覽圖片二維碼,或者通過 canvas 添加自定義 logo。除此之外,在組件內還提供了便捷的下載功能。這一解決方案為開發(fā)者在 Web 應用中集成二維碼生成功能提供了便捷而強大的工具。

希望這篇文章能夠幫助你更好地了解如何使用 Vue3 和 TypeScript 實現(xiàn) 生成二維碼功能!如果你有任何問題或建議,請隨時提出。

以上就是Vue3+TypeScript實現(xiàn)二維碼生成組件的詳細內容,更多關于Vue3+TypeScript二維碼的資料請關注腳本之家其它相關文章!

相關文章

  • vue實現(xiàn)簡單圖片上傳

    vue實現(xiàn)簡單圖片上傳

    這篇文章主要為大家詳細介紹了vue實現(xiàn)簡單圖片上傳功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • vxe-table?實現(xiàn)?excel?選擇一個單元格拖拽自動復制新的單元格(示例代碼)

    vxe-table?實現(xiàn)?excel?選擇一個單元格拖拽自動復制新的單元格(示例代碼)

    vxe-table是一款強大的表格組件,支持Excel風格的操作,通過鼠標右下角的擴展按鈕,用戶可以拖拽選擇單元格并自動復制內容到擴展區(qū)域的所有單元格中,本文通過示例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2025-01-01
  • 如何在vue3中優(yōu)雅的使用jsx/tsx詳解

    如何在vue3中優(yōu)雅的使用jsx/tsx詳解

    看了一些 Vue3 的組件庫源碼,發(fā)現(xiàn)無一例外都使用的jsx/tsx來實現(xiàn),而且實現(xiàn)方式也各不相同,下面這篇文章主要給大家介紹了關于如何在vue3中優(yōu)雅的使用jsx/tsx的相關資料,需要的朋友可以參考下
    2022-10-10
  • Vue中請求本地JSON文件并返回數(shù)據(jù)的方法實例

    Vue中請求本地JSON文件并返回數(shù)據(jù)的方法實例

    在前端開發(fā)過程當中,當后臺服務器開發(fā)數(shù)據(jù)還沒完善,沒法與咱們交接時,咱們習慣在本地寫上一個json文件做模擬數(shù)據(jù)測試代碼效果是否有問題,下面這篇文章主要給大家介紹了關于Vue中請求本地JSON文件并返回數(shù)據(jù)的相關資料,需要的朋友可以參考下
    2022-08-08
  • Vue項目打包部署后瀏覽器自動清除緩存問題的解決方法

    Vue項目打包部署后瀏覽器自動清除緩存問題的解決方法

    這篇文章主要介紹了vue打包部署后 瀏覽器緩存問題,導致控制臺報錯ChunkLoadError: Loading chunk failed的解決方案,文中有相關的圖文和代碼供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2024-12-12
  • 在vue+element-plus中無法同時使用v-for和v-if的問題及解決方法

    在vue+element-plus中無法同時使用v-for和v-if的問題及解決方法

    由于路由中存在不需要遍歷的數(shù)據(jù)所以像用v-if來過濾,但是報錯,百度說vue不能同時使用v-if和v-for,今天小編給大家分享解決方式,感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • vue實現(xiàn)下拉框的多選功能(附后端處理參數(shù))

    vue實現(xiàn)下拉框的多選功能(附后端處理參數(shù))

    本文介紹了如何使用Vue實現(xiàn)下拉框的多選功能,實現(xiàn)了在選擇框中選擇多個選項的功能,文章詳細介紹了實現(xiàn)步驟和示例代碼,對于想要了解如何使用Vue實現(xiàn)下拉框多選功能的讀者具有一定的參考價值
    2023-08-08
  • 使用Vue3和Echarts?5繪制帶有立體感流線中國地圖(推薦收藏!)

    使用Vue3和Echarts?5繪制帶有立體感流線中國地圖(推薦收藏!)

    最近接到一個需求是做一個中國地圖,下面這篇文章主要給大家介紹了關于如何使用Vue3和Echarts?5繪制帶有立體感流線中國地圖的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • vue百度地圖 + 定位的詳解

    vue百度地圖 + 定位的詳解

    這篇文章主要介紹了vue百度地圖 + 定位的詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • 淺談element關于table拖拽排序問題

    淺談element關于table拖拽排序問題

    本文主要介紹了element關于table拖拽排序問題,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評論

宣恩县| 托里县| 北京市| 大新县| 乡城县| 阿克苏市| 那坡县| 惠安县| 平罗县| 卓尼县| 丹凤县| 峨眉山市| 绥芬河市| 绩溪县| 鄂伦春自治旗| 三门峡市| 泉州市| 兴城市| 宜宾市| 余江县| 化德县| 嘉黎县| 开封县| 广东省| 永登县| 湖北省| 霍邱县| 扶绥县| 金溪县| 宝坻区| 云和县| 彭水| 云梦县| 遵义县| 沭阳县| 大港区| 县级市| 集贤县| 北碚区| 苗栗市| 高尔夫|