遇到這么一個需求:
車牌號輸入,並且是每次輸入后,每一位輸入字符在占一個格子。
由於車牌號的構成對於密碼而言比較復雜,否則可以模擬一個鍵盤,來控制和判斷輸入的內容,這樣這個效果就比較簡單。但是用於車牌輸入的鍵盤內容比較多,所以這邊用另外的方法。
首先創建一個input
<input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="bIsUnit?7:8" @blur="fBlur" />
添加一些基礎的事件,並且將其隱藏,隱藏樣式比較特殊,可在文末全部代碼處查看
然后創建方框等元素
<view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length}" :key="nIndex"> {{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}} </view>
當點擊方框時,輸入框聚焦,然后輸入的字符處理后挨個排放入框內。
但是這個完成后有個bug,
當輸入字符后,經過多次修改,尤其是在請求之后,隱藏的輸入框被聚焦時,光標會跳到最前,導致內容無法修改,或者輸入的字符永遠在已存在字符的前面。這種情況通過清空字符時解決不了的。
所以解決方案是在請求后重載組件,重載方法是在input上添加key,請求后改變key來實現組件重載
<comp-car @fCb="fCarIpt" ref="compcar" :key="nComp"></comp-car>
nComp: Math.random()
但是重載的方法在小程序上經過測試失效了,更改key並不能讓組件重載,但是小程序內測試時也未出現該bug,所以小程序內就直接清空字符處理后不再進行更多操作;
組件的全部代碼如下:
app:
<template>
<view class="car" @tap="fFocus">
<input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="bIsUnit?7:8" @blur="fBlur" />
<view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length}" :key="nIndex">
{{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}}
</view>
<view class="car-item car-change" @tap.stop="fChange"><i class="iconfont"></i><text>{{bIsUnit?'新能源':'普通'}}</text></view>
</view>
</template>
<script>
export default {
data() {
return {
sCar: '蘇',
bIsUnit: true,
bFocus: false,
cursor: 1
}
},
computed: {
cCarNum() {
return this.bIsUnit ? [0, 1, 2, 3, 4, 5, 6] : [0, 1, 2, 3, 4, 5, 6, 7]; //車牌位數
}
},
onLoad(option) {
},
methods: {
fClear() {
this.sCar = '蘇';
this.bIsUnit = true;
this.bFocus = false;
},
fChange() {
this.sCar = '蘇';
this.bFocus = false;
this.bIsUnit = !this.bIsUnit;
this.$emit('fCb', {
sCar: this.sCar.toUpperCase(),
bIsUnit: this.bIsUnit
})
},
fBlur() {
this.bFocus = false;
},
fFocus() {
this.bFocus = true;
},
fInput() {
this.$emit('fCb', {
sCar: this.sCar.toUpperCase(),
bIsUnit: this.bIsUnit
})
}
},
mounted() {
this.fClear()
}
}
</script>
<style scoped lang="less">
.car {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 44px;
width: 100%;
padding: 5px;
box-sizing: border-box;
}
.car-item {
height: 42px;
width: 36px;
margin: 0 2px;
text-align: center;
line-height: 42px;
color: #3e3e3e;
font-size: 18px;
border: 1px solid #b2b2b2;
border-radius: 3px;
}
.active {
border-color: #19bbff;
}
.ipt-hide {
position: absolute;
z-index: -1;
left: -100%;
opacity: 0
}
.car-change {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-style: dotted;
font-size: 10px;
line-height: 2;
color: #7f7f7f;
.iconfont {
font-size: 10px;
}
}
</style>
小程序內代碼稍有改動,遍歷渲染字符串時可以直接使用數字而不用數組
小程序代碼:
<template>
<view class="car" @tap="fFocus">
<input :focus="bFocus" type="text" v-model="sCar" class="ipt-hide" @input="fInput" :maxlength="cCarNum" @blur="fBlur" />
<view class="car-item" v-for="nIndex in cCarNum" :class="{active:nIndex===sCar.length-1}":key="nIndex">
{{sCar.split('')[nIndex]?sCar.split('')[nIndex].toUpperCase():''}}
</view>
<view class="car-item car-change" @tap.stop="fChange"><i class="iconfont"></i><text>{{bIsUnit?'新能源':'普通'}}</text></view>
</view>
</template>
<script>
export default {
data() {
return {
sCar: '蘇',
bIsUnit: true,
bFocus: false
}
},
computed: {
cCarNum() {
return this.bIsUnit ? 7 : 8; //車牌位數
}
},
onLoad(option) {
},
methods: {
fClear() {
this.sCar = '蘇';
this.bIsUnit = true;
this.bFocus = false;
},
fChange() {
this.sCar = '蘇';
this.bFocus = false;
this.bIsUnit = !this.bIsUnit;
},
fBlur() {
this.bFocus = false;
},
fFocus() {
this.bFocus = true;
},
fInput() {
this.$emit('fCb', {
sCar: this.sCar.toUpperCase(),
bIsUnit: this.bIsUnit
})
}
},
mounted() {
this.fClear()
}
}
</script>
<style scoped lang="less">
.car {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 42px;
width: 100%;
padding: 5px;
box-sizing: border-box;
}
.car-item {
height: 42px;
width: 36px;
margin: 0 2px;
text-align: center;
line-height: 42px;
color: #3e3e3e;
font-size: 18px;
border: 1px solid #b2b2b2;
border-radius: 3px;
}
.active {
border-color: #19bbff;
}
.ipt-hide {
position: absolute;
z-index: -1;
left: -100%;
opacity: 0
}
.car-change {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-style: dotted;
font-size: 10px;
line-height: 2;
color: #7f7f7f;
.iconfont {
font-size: 10px;
}
}
</style>
