Client-Side QR Code Generation and Printing in Vue.js
To implement printable QR code functionality in Vue applications, install the following dependencies:
npm install vue-qr html2canvas print-js
# or
yarn add vue-qr html2canvas print-js
Configure the templaet structure with a dialog container for the QR preview:
<template>
<el-dialog
:visible.sync="dialogVisible"
title="Scan Code"
width="600px"
:close-on-click-modal="false"
@closed="handleClose"
class="print-dialog"
>
<div ref="captureTarget" class="code-wrapper">
<div class="qr-container">
<vue-qr
:text="qrContent"
:size="200"
:margin="2"
colorDark="#1a73e8"
colorLight="#ffffff"
:correctLevel="3"
:logoSrc="logoUrl"
:logoScale="0.2"
:logoCornerRadius="8"
/>
</div>
</div>
<div slot="footer" class="actions">
<el-button @click="dialogVisible = false">Close</el-button>
<el-button type="primary" @click="executePrint">Print</el-button>
</div>
</el-dialog>
</template>
Import the required libraries in your component:
import VueQrcode from 'vue-qr'
import html2canvas from 'html2canvas'
import printJS from 'print-js'
export default {
components: {
VueQrcode
},
data() {
return {
dialogVisible: false,
qrContent: '',
logoUrl: require('@/assets/logo.png'),
merchantInfo: {}
}
},
methods: {
executePrint() {
const element = this.$refs.captureTarget
const config = {
scale: 2,
useCORS: true,
allowTaint: true,
backgroundColor: null,
logging: false
}
html2canvas(element, config).then(canvas => {
const imageData = canvas.toDataURL('image/png')
printJS({
printable: imageData,
type: 'image',
documentTitle: this.merchantInfo.name || 'QR Code',
imageStyle: 'width:100%;max-width:500px;'
})
this.dialogVisible = false
})
},
handleClose() {
this.qrContent = ''
}
}
}
Apply styles to ensure proper rendernig and positioning:
.code-wrapper {
width: 100%;
height: 500px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
.qr-container {
background: white;
padding: 24px;
border-radius: 16px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
img {
display: block;
}
}
}
.actions {
display: flex;
justify-content: flex-end;
gap: 12px;
}