遇到這么一個需求:
車牌號輸入,並且是每次輸入后,每一位輸入字符在占一個格子。
由於車牌號的構成對於密碼而言比較復雜,否則可以模擬一個鍵盤,來控制和判斷輸入的內容,這樣這個效果就比較簡單。但是用於車牌輸入的鍵盤內容比較多,所以這邊用另外的方法。
首先創建一個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>