## 前言
微信小程序中,需要為用戶輸入提供安全密碼,用于后續(xù)的操作。例如支付密碼的初始設(shè)置、修改、手機(jī)號(hào)的更換、支付金額等操作。絕大部分的設(shè)計(jì)都會(huì)如圖所示:

密碼輸入框
這里我就來簡單的說說如何實(shí)現(xiàn)這個(gè)《微信小程序:自定義驗(yàn)證碼或者密碼輸入框組件》。
由于一個(gè)項(xiàng)目中會(huì)多次使用,所以這里決定把它做成一個(gè)組件的形式。
## code(****代碼****)
wxml:(代碼中注釋的部分是另一種寫法,如果開啟,請(qǐng)把 input 模式注釋掉,樣式什么的無需修改)
<view class="indep-password-box">
<view class="indep-password-box__wrapper">
<block wx:for="{{inputLength}}" wx:key="*this">
<!-- input模式 -->
<input class="indep-password-box__item"
type="number"
catchtap="_focusInput"
password="{{!showValue}}"
disabled
value="{{currentValue.length >= index + 1 ? currentValue[index] : ''}}"
style="width: {{inputWidth}}; height: {{inputHeight}};"
></input>
<!-- 自定義模式:隱藏密碼時(shí),小圓點(diǎn)(自定義)\顯示密碼時(shí),顯示對(duì)應(yīng)的值 -->
<!-- <view class="indep-password-box__item"
catchtap="_focusInput"
style="width: {{inputWidth}}; height: {{inputHeight}}"
>
<view wx:if="{{!showValue && currentValue.length >= index + 1}}" class="indep-password-box__item-hidden"></view>
<view wx:if="{{showValue}}"
class="indep-password-box__item-show"
>{{currentValue.length >= index + 1 ? currentValue[index] : ''}}</view>
</view> -->
</block>
<input class="indep-password-box__input-hidden"
type="number"
password="{{true}}"
value="{{currentValue}}"
maxlength="{{inputLength}}"
focus="{{inputFocus}}"
bindinput="_setCurrentValue"
bindblur="_onInputFocus"
></input>
</view>
</view>
json:
{
"component": true,
"usingComponents": {}
}
js:
Component({
properties: {
// 輸入框的數(shù)量
inputLength: {
type: Number,
value: 6
},
// 單個(gè)輸入框的寬度
inputWidth: {
type: String,
value: '100rpx'
},
inputHeight: {
type: String,
value: '100rpx'
},
// 是否顯示輸入的值,默認(rèn)隱藏
showValue: {
type: Boolean,
value: false
}
},
data: {
// input是否獲取焦點(diǎn)
inputFocus: false,
// 初始input值為空
currentValue: ''
},
methods: {
// 設(shè)置當(dāng)前的值
_setCurrentValue (e) {
// 在此處判斷滿6(inputLength)位,把值返回給上級(jí)父組件或頁面
let currentValue = e.detail.value
// 改變時(shí),派發(fā)一個(gè)事件,如果父組件或頁面中需要實(shí)時(shí)獲取改變后的值,可以監(jiān)聽這個(gè)事件。
this.triggerEvent('change', e.detail.value)
this.setData({ currentValue })
if (currentValue.length >= this.data.inputLength) {
this._complete(e.detail.value)
return
}
},
// 點(diǎn)擊偽裝的input時(shí),讓隱藏的input獲得焦點(diǎn)
_focusInput (event) {
console.log('點(diǎn)擊偽裝的input時(shí),讓隱藏的input獲得焦點(diǎn)', event)
this.setData({ inputFocus: true })
},
// 派發(fā)完成事件
_complete (value) {
console.log('派發(fā)完成事件', value)
this.triggerEvent('complete', value)
this.setData({ inputFocus: false })
},
// 處理文本框失焦
_onInputFocus (event) {
console.log('處理文本框失焦', event)
this.setData({ inputFocus: false })
},
// 提供給外部調(diào)用的方法,顯示/隱藏密碼。接收一個(gè)參數(shù),可以顯性修改展示的狀態(tài)。
toggleValue (state) {
this.setData({ showValue: state != undefined ? state : !this.data.showValue })
},
// 清除input當(dāng)前的值
clearCurrentValue () {
this.setData({ currentValue: '' })
}
}
})
wxss:
.indep-password-box {
display: flex;
justify-content: center;
align-items: center;
}
.indep-password-box__wrapper {
display: flex;
flex-direction: row;
}
/* 子項(xiàng) */
.indep-password-box__wrapper .indep-password-box__item {
/* 自定義模式 */
position: relative;
display: flex;
justify-content: center;
align-items: center;
/* input模式 */
border: 1px solid #999;
box-sizing: border-box;
font-size: 12px;
text-align: center;
}
/* 邊框重疊 */
.indep-password-box__wrapper .indep-password-box__item + .indep-password-box__item {
margin-left: -1rpx;
}
/* 小圓點(diǎn) */
.indep-password-box .indep-password-box__wrapper .indep-password-box__item-hidden {
width: 14rpx;
height: 14rpx;
border-radius: 50%;
background: #999;
}
/* 對(duì)應(yīng)值 */
.indep-password-box .indep-password-box__wrapper .indep-password-box__item-show {
color: #087b46;
}
/* 隱藏的輸入框 */
.indep-password-box__wrapper .indep-password-box__input-hidden {
width: 0;
height: 0;
}
app.json:不要忘記在app.json中注冊(cè)組件,(本人是在根目錄下創(chuàng)建的/components/目錄)
// ...
"usingComponents": {
// ...
"indep-password-box": "/components/password-box/password-box",
// ...
}
## used(****使用****)
上面是組件的定義,接下來看看如何在頁面中使用它。
<indep-password-box id="passwordBox"
inputLength="{{6}}"
inputWidth="100rpx"
inputHeight="100rpx"
showValue="{{false}}"
bind:complete="setupPasswordComplete"
></indep-password-box>
onShow: function () {
this.passwordBox = this.selectComponent('#passwordBox') // 獲取密碼框組件,用來操作組件內(nèi)部的方法
},
methods: {
// 設(shè)置密碼
setupPasswordComplete (event) {
// console.log('setupPasswordComplete', event.detail)
this.setData({ 'password': event.detail })
},
// 清除密碼
clearPassword() {
this.passwordBox.clearCurrentValue() // 調(diào)用組件內(nèi)部的清除方法,清空輸入的值
},
}
## 設(shè)計(jì)思路
設(shè)置寬高為0的方式隱藏文本框,并把隱藏的文本框作為輸入的來源,通過選中單個(gè)框的點(diǎn)擊事件,為隱藏的文本框獲得焦點(diǎn),再以此文本框的輸入值,作為循環(huán)進(jìn)行展示。
提示:后面還有精彩敬請(qǐng)期待,請(qǐng)大家關(guān)注我的專題:web前端。如有意見可以進(jìn)行評(píng)論,每一條評(píng)論我都會(huì)認(rèn)真對(duì)待。