如果使用弹窗显示二维码, 那就涉及父子组件传值。
在父子组件的生命周期中, mounted() 触发的顺序是先子后父,控制台打印如下:
所以使用 mounted()去触发转换二维码的方法,控制台肯定会报错cannot read property"appendChild’ of undefined 。
因为你获取这节点时,节点还没加载。弹窗的页面还没有被挂载到,就执行了这个方法,所以就会报错。
加 nextTick() 或者 加延时函数 setTimeOut() 都是没有用的。
后面去看了element官网里面的Dialog的API,其实在Dialog 打开动画结束时的回调 opened() 里面触发这个二维码就可以了
所以一定要在opened里面去执行二维码的转换,不然就会报错。
@opened="showCode"
安装插件
cnpm install qrcodejs2 --save
页面引入
import QRCode from 'qrcodejs2
父组件传值:
btnClick(val) {
// 二维码弹窗
this.codeDialogVisible = true
let url = window.globalConfig.base.ip + ':' + window.globalConfig.base.backend_port + val.downloadPath
let dowmloadUrl = url.replace(/\\/g, '/')
// 下载地址进行转码
this.paths = encodeURI(dowmloadUrl)
},
Dialog弹窗的完整代码:
<template>
<div>
<el-dialog
v-dialogDrag
title="扫描二维码下载"
:width="dialogWidth + 'px'"
:visible.sync="show"
:close-on-click-modal="false"
@opened="showCode"
@close="cancel"
>
<div ref="qrcode" class="codeStyle" />
</el-dialog>
</div>
</template>
<script>
import QRCode from 'qrcodejs2'
export default {
props: {
dialogVisible: { type: Boolean }, // 弹窗显示
dialogWidth: { type: Number, default: 400 }, // 弹窗宽度
paths: { type: String, default: '' } // 文件下载路径
},
data() {
return {}
},
computed: {
show: {
get() {
return this.dialogVisible
},
set(val) {
return this.$emit('cancel', val)
}
}
},
methods: {
/** 显示二维码图片 */
showCode() {
this.creatCode()
},
/** 转换二维码 */
creatCode() {
// 清除上一张二维码的缓存
this.$refs.qrcode.innerHTML = ''
let qrcode = new QRCode(this.$refs.qrcode, {
width: 200,
height: 200,
render: 'canvas',
correctLevel: QRCode.CorrectLevel.H
})
// 对所需要的内容进行转码
qrcode.makeCode(this.paths)
let canvas = document.querySelector('canvas')
var pic= canvas.toDataURL('image/png')
canvas.outerHTML = '<img alt="Scan me!" src=' + pic+ ' style="display: block;">'
qrcode.clear()
},
/** 弹窗关闭 */
cancel() {
this.show = false
}
}
}
</script>
<style scoped>
.codeStyle{
margin: 20px;
background: #9093993d;
width: 200px;
height: 200px;
margin: auto;
margin-bottom: 30px;
}
</style>
效果如下: