完整代码:
<template>
<view class="password-input-com" ref="passwordInputCom">
<input
ref="passwordInput"
v-model="inputValue"
:focus="inputFocus"
:type="type"
:inputmode="inputmode ? inputmode : (type == 'number' ? 'numeric' : '')"
:maxlength="maxLength"
@input="onInput"
@blur="blur"
class="password-input"
:class="{'is-h5': platform == 'H5'}">
<view class="virtual-input-list" ref="virtualInputList">
<view class="virtual-input-item"
v-for="(item, index) in maxLength"
:key="index"
:class="{security: mask, 'input-focus': index == virtualInputItemIndex}"
@click="onVirtualInputClick(index)">
<view v-if="!mask" class="text-viewer">{{inputValue[index]}}</view>
<view v-show="!!inputValue[index] && mask" class="security-mask"></view>
<view
class="virtual-input-cursor"
:class="{'is-h5': platform == 'H5'}"></view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "PasswordInput",
options: {
virtualHost: true
},
props: {
value: {
type: String,
default: ''
},
maxLength: { // 密码最大长度
type: Number,
default: 6
},
mask: {
type: Boolean,
default: false
},
type: {
type: String,
default: 'number'
},
inputmode: {
type: String,
default: ''
}
},
data() {
// 获取运行平台
let getPlatform = () => {
let platform;
// #ifdef H5
platform = 'H5';
// #endif
// #ifdef MP-WEIXIN
platform = 'mp-weixin';
// #endif
// #ifdef MP-ALIPAY
platform = 'mp-alipay';
// #endif
return platform;
};
return {
platform: getPlatform(),
virtualInputs: [],
// specialStr: '●', // 特殊字符
// splitStr: '★', // 分割字符
inputValue: '',
inputFocus: false,
passwordInputLeft: 1,
virtualInputItemIndex: -1
};
},
watch: {
value: {
immediate: true,
handler(newVal){
// this.calcVirtualInputs(newVal);
console.log('监听value:', newVal);
if (this.inputValue == newVal + '') {
return;
}
this.inputValue = newVal + '';
}
}
},
methods: {
// 计算需要输入框的个数
calcVirtualInputs(newVal){
let valueArr = ((newVal + '').length > 0 ? (newVal + '') : '●●●●●●●●●●●●●●●●●●●●●●●●').split('');
let length = this.maxLength;
// console.log('valueArr', valueArr)
if(valueArr.length > length){
valueArr.splice(length);
}else if(valueArr.length < length){
let lengthDiff = length - valueArr.length;
while(lengthDiff > 0){
valueArr.push('●');
lengthDiff--;
}
}
let virtualInputs = valueArr.map((str, index) => {
return {
value: str == '●' ? ' ' : str,
focus: false,
index: index
};
});
this.virtualInputs = virtualInputs;
},
onInput(evt){
let val = '';
if(this.platform == 'H5'){
val = evt.target.value;
} else {
val = evt.detail.value;
}
let maxLength = this.maxLength;
val = val.substr(0, maxLength);
this.inputValue = val;
this.virtualInputItemIndex = val.length;
this.$emit('input', val);
if (val.length == maxLength) {
this.inputFocus = false;
this.virtualInputItemIndex = -1;
let timer = setTimeout(() => { // 输入完最后一个字符后再抛出complete事件
clearTimeout(timer);
this.$emit('complete', val);
}, 0);
}
// this.calcVirtualInputs(val);
},
onVirtualInputClick(index){
console.log('onVirtualInputClick', index)
this.inputFocus = true;
// this.inputValue = virtualInputVal == ' ' ? virtualInputVal : (' ' + virtualInputVal);
let val = this.inputValue;
this.virtualInputItemIndex = val.length > 0 ? val.length : 0;
if(this.platform == 'H5'){
console.log('this.$refs.passwordInput', this.$refs.passwordInput);
this.$refs.passwordInput.focus();
}
},
getValue(){
return this.inputValue;
},
blur(){
this.inputFocus = false;
this.virtualInputItemIndex = -1;
},
focus () {
this.inputFocus = false;
this.virtualInputItemIndex = this.inputValue.length;
if(this.platform == 'H5'){
this.$refs.passwordInput.focus();
}
}
}
}
</script>
<style lang="scss">
.password-input-com {
position: relative;
}
.password-input {
position: absolute;
top: -600rpx; // 隐藏在真机情况下的原生光标
left: 2rpx;
width: 100%;
height: 100%;
line-height: 1.5;
/* color: rgba(255,255,255,0.8); */
color: transparent;
font-size: 48rpx;
text-align: center;
opacity: 0;
background-color: transparent;
&.is-h5{
top: 2rpx;
}
}
.virtual-input-list {
position: relative;
z-index: 2;
display: flex;
justify-content: space-between;
width: 100%;
height: 70rpx;
opacity: 0.7;
.virtual-input-item {
position: relative;
width: 70rpx;
height: 100%;
border: 2rpx solid #90949D;
transition: border-color .3s;
.text-viewer {
height: 100%;
line-height: 1.5;
text-align: center;
color: #202328;
font-size: 48rpx;
}
.security-mask {
position: absolute;
top: 50%;
left: 50%;
width: 24rpx;
height: 24rpx;
z-index: 4;
border-radius: 50%;
margin: -12rpx 0 0 -12rpx;
background-color: #202328;
}
.virtual-input-cursor {
display: none;
position: absolute;
top: 10%;
left: 50%;
height: 80%;
z-index: 6;
width: 3rpx;
background-color: #202328;
animation: 0.6s virtual-input-cursor infinite;
}
&.input-focus {
border-color: #387EE8;
.virtual-input-cursor {
display: block;
&.is-h5{
display: block;
}
}
}
}
}
@keyframes virtual-input-cursor {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
</style>
9***@qq.com (作者)
我把focus的值设置为true,在微信小程序中渲染后也没有focus属性,这就导致了无法自动弹起软键盘
2023-07-04 15:53