源代码地址
: https://github.com/HYzihong/vue3_use_case
git
: https://github.com/HYzihong/vue3_use_case.gjt
引入 qrcode-vue3
pnpm i qrcode-vue3 -D
自定义qrcode组件
<template>
<div>
<div v-if="imageUrl" :class="containerClass">
<img :src="imageUrl" :class="imageClass" @click="downloadImage" crossorigin="anonymous" />
</div>
</div>
</template>
<script lang="ts" setup>
import QRCodeStyling from 'qrcode-vue3/src/core/QRCodeStyling';
import { onMounted, ref, watch } from 'vue';
import { donwloadBase64Image } from '../hooks/useDownLoadBase64Image';
const props = defineProps({
width: {
type: Number,
default: 300,
},
imageClass: {
type: String,
default: '',
},
containerClass: {
type: String,
default: '',
},
downloadButton: {
type: String,
default: '',
},
buttonName: {
type: String,
default: 'Download3',
},
height: {
type: Number,
default: 300,
},
value: {
type: String,
required: true,
},
image: {
type: String,
default: '',
},
qrOptions: {
type: Object,
default: () => ({
typeNumber: 0,
mode: 'Byte',
errorCorrectionLevel: 'Q',
}),
},
imageOptions: {
type: Object,
default: () => ({ hideBackgroundDots: true, imageSize: 0.4, margin: 0 }),
},
dotsOptions: {
type: Object,
default: () => ({
type: 'dots',
color: '#6a1a4c',
gradient: {
type: 'linear',
rotation: 0,
colorStops: [
{ offset: 0, color: '#6a1a4c' },
{ offset: 1, color: '#6a1a4c' },
],
},
}),
},
backgroundOptions: {
type: Object,
default: () => ({ color: '#ffffff' }),
},
cornersSquareOptions: {
type: Object,
default: () => ({ type: 'dot', color: '#000000' }),
},
cornersDotOptions: {
type: Object,
default: () => ({ type: undefined, color: '#000000' }),
},
fileExt: {
type: String,
default: 'png',
},
download: {
type: Boolean,
default: false,
},
fileName: {
type: String,
default: '二维码.png',
},
downloadOptions: {
type: Object,
default: () => ({ name: 'vqr', extension: 'png' }),
},
});
const imageUrl = ref<string>('');
const qrCode = ref(
new QRCodeStyling({
data: props.value,
width: props.width,
height: props.height,
qrOptions: props.qrOptions,
imageOptions: props.imageOptions,
dotsOptions: props.dotsOptions,
backgroundOptions: props.backgroundOptions,
image: props.image,
cornersSquareOptions: props.cornersSquareOptions,
cornersDotOptions: props.cornersDotOptions,
}),
);
watch(
() => props.value,
async () => {
qrCode.value = new QRCodeStyling({
data: props.value,
width: props.width,
height: props.height,
qrOptions: props.qrOptions,
imageOptions: props.imageOptions,
dotsOptions: props.dotsOptions,
backgroundOptions: props.backgroundOptions,
image: props.image,
cornersSquareOptions: props.cornersSquareOptions,
cornersDotOptions: props.cornersDotOptions,
});
imageUrl.value = await qrCode.value.getImageUrl(props.fileExt);
},
);
onMounted(async () => {
imageUrl.value = await qrCode.value.getImageUrl(props.fileExt);
});
function downloadImage(): void {
console.log('base64 data =>', imageUrl.value);
if (props.download) {
donwloadBase64Image(imageUrl, props.fileName);
}
}
</script>
自定义二维码下载
import { Ref } from 'vue';
export const donwloadBase64Image = (data: Ref<string>, fileName: string): void => {
const aLink = document.createElement('a');
const blob = base64ToBlob(data);
const evt = document.createEvent('HTMLEvents');
evt.initEvent('click', true, true);
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
};
function base64ToBlob(code: Ref<string>): any {
const parts = code.value.split(';base64,');
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}