有没有实现用PDA扫描二维码或者一维码获取数据操作的? 其实是一个简单的输入框封装
要求
- 拿起扫码枪随时可扫,焦点随时必须在输入框内(使用定时器手动获取焦点)
- 需要绑定一个值实现父子组件的值同步(使用v-model)
- 需要给其他输入框需要输入时让出焦点(控制是否获取焦点)
- 扫码输入框不能拉起软键盘,其他输入框需要拉起软键盘(添加readonly属性)
以以上几点来完成扫描框组件
添加一个scanInput.vue
<view class="scan">
<uni-easyinput id="scaninput" :auto-blur="false" ref="scanInputRef"
class="scaninput" :focus='focusState'
:clearable="false" v-model="scanValue" :placeholder="placeholder"
@blur='focusBlur' @focus="focusDo" @confirm="confirmDo">
</uni-easyinput>
<!-- 遮住input框 不点到其弹起软键盘 -->
<view class="masksty">
<view class="vm" style="background: #fff;">
<uni-icons type="close" v-if="inputValue" size="27" class="vm"
@click="clearDo" color="#999"></uni-icons>
<uni-icons type="scan" size="26" class="vm" @click="iconClick"
color="#3DCEC9"></uni-icons>
</view>
</view>
</view>
</template>
<script setup>
/*
说明:更改传入的isFous焦点状态来确认是否获取焦点,true:获取,false:不获取
props参数:inputValue 输入框值
isFous 是否获取扫描框焦点
placeholder 扫描框占位符
回调函数:@scanSuccess 扫描成功回调 返回扫描的值
@iconClick 点击扫描按钮触发 返回扫描框的值
@clear 点击清除按钮触发 没有返回
@confirm 点击完成按钮触达 返回扫描框的值
*/
import {ref,reactive,defineProps,defineEmits,watch,} from 'vue';
import {onReady,onLoad,} from '@dcloudio/uni-app'
//接收到的参数
const props = defineProps({
placeholder: String, //占位符
isFous: Boolean, //是否需要聚焦
inputValue: String, //输入框值
})
//@scanSuccess 扫描成功回调
const emit = defineEmits(['update:inputValue', "scanSuccess",
'iconClick', 'clear', 'confirm'])
let scanTimer = ref(null);
let scanValue = ref('');
let scanInputRef = ref();
let focusState = ref(true);
onLoad(() => {
focusState.value = props.isFous;
scanValue.value = props.inputValue
//监听值变化,并回调
watch(scanValue, (newVal, oldVal) => {
// console.log('newVal',newVal);
emit('update:inputValue', newVal)
if(!newVal) return
if (newVal) {
emit("scanSuccess", newVal);
}
})
watch(() => props.isFous, (newVal, oldVal) => {
if (newVal) { //是
focusState.value = true;
hideKeyboard();
} else {
destroyTimer(); //否
}
})
watch(() => props.inputValue, (newVal, oldVal) => {
scanValue.value = newVal
})
})
function updateInput() {
emit('update:inputValue', scanValue.value)
}
/**
* 创建定时任务 始终获取焦点[两输入框时,输入完成后,创建任务]
*/
function createTimer() {
scanTimer.value = setInterval(function() {
// console.log('监听聚焦');
focusState.value = true;
//获取焦点后 清除定时器
clearInterval(scanTimer.value);
hideKeyboard();
}, 1300)
}
/**
* 销毁定时任务[例如页面上有两输入框时,在输入框聚焦时销毁该任务,防止条码框一直聚焦无法输入]
*/
function destroyTimer() {
clearInterval(scanTimer.value);
focusState.value = false;
}
//扫描框失去焦点时现更改状态 然后定时手动聚焦
function focusBlur() {
if (focusState.value) {
focusState.value = false;
createTimer();
}
}
//获取到焦点更改状态
function focusDo() {
focusState.value = true;
clearInterval(scanTimer.value);
hideKeyboard();
}
//隐藏软键盘
function hideKeyboard() {
let scanInputEle = document.querySelector('#scaninput input');
if (scanInputEle) {
scanInputEle.setAttribute("readonly", true);
setTimeout(() => {
scanInputEle.removeAttribute("readonly");
}, 100);
}
}
function iconClick() {
//点击扫描图标触发,返回扫描框的值
emit("scanSuccess", scanValue.value);
}
//点击清除按钮时操作
function clearDo() {
scanValue.value = '';
emit('update:inputValue', scanValue.value)
emit("clear");
}
//点击确认时操作
function confirmDo() {
emit("confirm", scanValue.value);
}
</script>
<style lang="scss">
.scan {
padding: 28rpx 30rpx;
position: relative;
.masksty {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: transparent;
padding: 38rpx 46rpx;
text-align: right;
}
.closeico {}
.scaninput {
:deep(.is-input-border) {
border: 1px solid #3DCEC9 !important;
border-radius: 32rpx !important;
}
:deep(.uni-icons) {
color: #3DCEC9 !important;
}
}
}
</style>
使用
import scanInput from '../../components/scanInput.vue'
</script>
<scan-input :placeholder="'请将设备对准条形码进行扫描'"
v-model:inputValue="inputValue" :isFous='scanFous'
@scanSuccess="scanSuccess" @clear="clearScan"></scan-input>
<uni-easyinput v-model="em.scannedNum" placeholder="请输入本次出库数量"
type="number" @focus="scanFous = false" @blur="scanFous = true"></uni-easyinput>
其实这个组件最头痛的是收起输入法的软键盘,uni有一个API hideKeyboard()方法,但是这里使用就是一个坑,键盘到是收起来了,但是却再也获取不到焦点了,官方也没有提出解决方法,就只能自己小试牛刀了,而且uni内部组件input的封装也没有readonly的属性,姑且按照H5的方式给input加一个readOnly的属性来不弹起输入法软键盘,h5是亲测可用,打包成APP待验证~