使用场景: uniapp + uqrcode,根据内容变化,动态生成二维码。仅在触发时,弹窗显示。
例如,给工厂定制的App能够改变IP地址,为什么能够改IP地址,因为不同厂的内网IP不一样,每次打包成安装包之后,只需要一个用户可以自行配置IP地址,然后生成二维码,其它用户扫一扫就可以了,这样就会相对方便快捷。
流程: 点击按钮 ==> 弹窗显示二维码 ==> 修改配置 ==> 二维码更新 ==> 关闭弹窗
但在实际中,遇到了一些问题。
例如:
写在弹窗中,重复调用make函数为什么会报错,甚至导致App重启;
或者重复调用make函数为什么没有报错也没有重绘,
或者为什么popup弹窗关闭之后,再次make之后就显示空白?
这些坑,我不知道如何去解决,
但是我找到一条可行的路!!!
接下来请跟着我写。仅限uniapp,微信小程序等不知道,自行测试。
第一步:在uniapp插件市场下载UQRcode导入项目,下载完之后就能在项目中使用uqrcode标签。
<uqrcode ref="QRCode" value="12345" :size="100" canvas-id="qrcode"></uqrcode>
如果能看到二维码,就成功了第一步,当然没看到的话,看看是不是没有定义宽度高度,在标签对里增加class就行,class要自己写,定义宽度高度就行,这里宽度高度要和 size=100 的这个100一致,100是二维码大小,可以改。value就是二维码的内容。
第二步:把这个放在popup弹窗里,但是一上来就渲染有点问题,所以就需要在标签上增加start属性,以下仅显示属性增加项
<uqrcode
class="uqrcode"
:options="{ errorCorrectLevel:1, foregroundColor:'darkseagreen' }"
:start="false">
</uqrcode>
增加了class类,定义宽度高度
增加了options第一个定义了纠错等级,1234,纠错等级越高,二维码越大,少量字符用1就行,后面那个是颜色,按需修改就行。
start改为false就是让这个组件一上来不去自动生成二维码。
那么怎么生成二维码呢?需要获取到该组件,然后调用make方法
// Vue 2
this.$refs.QRCode.make(); // 方式1
this.$refs['QRCode'].make(); // 方式2
/**
Vue3 需要先引用
import { ref } from 'vue';
然后在setup函数里写
setup() {
const QRCode = ref(null);
return { QRCode }
}
*/
popup.value.open(); // 这里的popup同上写 const...ref(null); 变量名不一样,基本操作
setTimeout(()=>{
QRCode.value.make();
},1000)
逻辑:点击按钮或者什么触发事件,执行popup.value.open()弹窗打开。
然后界面绘制uqrcode组件,然后一秒之后,QRCode组件实例调用make()绘制二维码
此时:如果value绑定的vue里的响应式的值,那么value改变,二维码会自动重绘。不想重绘就把值定死就行。
第三步,关闭弹窗,在打开弹窗,发现二维码变没了。
重新赋值一边就行。
贴上全部代码!
<template>
<button @tap="pageFuncs.runOpen">open</button>
<uni-popup ref="popup" type="center" :isMaskClick="false">
<div class="model">
<div class="title">
<text class="t-font">服务器配置</text>
<uni-icons class="t-icon" type="closeempty" size="20" @tap="pageFuncs.runClose"></uni-icons>
</div>
<div class="under-line"></div>
<div class="content">
<div class="con-qr">
<uqrcode class="uqrcode" ref="QRCode" :options="{ errorCorrectLevel:1, foregroundColor:'darkseagreen' }" :value="data.curl" :size="100" :start="false" canvas-id="qrcode"></uqrcode>
<div class="qrcode-config">本机配置码</div>
</div>
<div></div>
<div class="config-inputs">
<div class="one-input">
<div class="in-mes">MES系统</div>
<input type="text" v-model="data.url.mes">
</div>
<div>
<div>工具系统</div>
<input type="text" v-model="data.url.tool">
</div>
</div>
</div>
<div class="under-line"></div>
<div class="btns">
<div class="btn-every" @tap="pageFuncs.runScancode">扫配置码</div>
<div class="btn-inline"></div>
<div class="btn-every" :class="{ 'btn-every-fix':data.areUpdate }">手动配置</div>
<div class="btn-inline"></div>
<div class="btn-every" :class="{ 'btn-every-fix':!data.areUpdate }">确认修改</div>
</div>
</div>
</uni-popup>
</template>
<script>
import { ref, reactive, onMounted, computed } from "vue";
export default {
setup() {
// 变量定义区域
const QRCode = ref(null);
const popup = ref(null);
const data = reactive({
areUpdate: false,
curl:'',
url:{mes:'http://192.168.0.1:8080',tool:'http://192.168.0.1:8080'}
})
data.areUpdate = computed(()=>{
let Config = uni.getStorageSync('appConfig');
if(!Config) Config = JSON.stringify(data.url)
if(Config == JSON.stringify(data.url)) return false
else return true
})
// 方法区域
const pageFuncs = {
// 在界面上点击了扫配置码,进而开启摄像头扫码
runScancode() {
uni.scanCode({
success(res) {
console.log('扫码结果', res.result)
}
})
},
// 关闭弹窗
runClose() {
popup.value.close();
},
// 打开弹窗
async runOpen() {
await popup.value.open();
await new Promise(re=>{ setTimeout(()=>{re()}, 50) })
QRCode.value.make();
data.curl = 'null';
await new Promise(re=>{ setTimeout(()=>{re()}, 50) })
data.curl = JSON.stringify(data.url);
},
//
}
// 挂载区域
onMounted(()=>{
pageFuncs.runOpen();
})
return { data, QRCode, popup, pageFuncs }
}
}
</script>
<style lang="scss" scoped>
.model{
width: 650rpx;
height: auto;
min-height: 200rpx;
padding: 0rpx;
max-height: 60vh;
background: #FFFFFF;
border-radius: 8rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
}
.title{
width: 100%;
height: 60rpx;
// background: skyblue;
font-weight: bold;
letter-spacing: 2rpx;
padding: 0rpx 20rpx;
margin: 6rpx 0rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
}
.t-font{
font-size: 28rpx;
}
.t-icon{
}
.under-line{
width: 94%;
height: 3rpx;
background: #dddddd;
margin-left: 3%;
border-radius: 1rpx;
}
.content{
width: 100%;
height: 260rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
// background: olive;
}
.con-qr{
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.uqrcode{
background: transparent;
margin: 1rpx 0rpx 0rpx 22rpx;
}
.qrcode-config{
font-size: 18rpx;
font-weight: bold;
letter-spacing: 2rpx;
background: darkseagreen;
display: inline-block;
color: #FFF;
padding: 2rpx 6rpx;
border-radius: 4rpx;
position: relative;
top: 10rpx;
left: 4rpx;
}
.config-inputs{
}
.one-input{
width: 400rpx;
height: 60rpx;
border: 2rpx solid #ccc;
border-radius: 16rpx;
position: relative;
}
.in-mes{
padding: 0rpx 10rpx;
font-size: 22rpx;
background: #FFF;
position: absolute;
top: -12rpx;
left: 20rpx;
}
.btns{
width: 100%;
height: 58rpx;
// background: darkcyan;
padding: 6rpx 0rpx;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.btn-every{
width: 33%;
height: 100%;
// outline: 1px solid red;
letter-spacing: 2rpx;
font-size: 26rpx;
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
color: #3A3F9B ;
}
.btn-every-fix{
color: #dddddd;
}
.btn-inline{
width: 3rpx;
height: 30rpx;
background: #dddddd;
border-radius: 1rpx;
}
</style>
复制到uniapp就行!