uniapp自定義驗證碼輸入框并隱藏光標
一. 前言
先看下使用場景效果圖:
- 點擊輸入框喚起鍵盤,藍框就相當于input的光標,驗證碼輸入錯誤或者不符合格式要求會將字體以及邊框改成紅色提示,持續(xù)1s,然后清空數(shù)據(jù),恢復(fù)原邊框樣式;
- 5位驗證碼輸入完畢,點擊頁面其他位置,隱藏鍵盤;這時如果發(fā)現(xiàn)驗證碼有誤,再次點擊輸入框又喚起鍵盤,也能正常刪除數(shù)字(這里其實做的時候遇到了bug,再次聚焦不能刪除錯誤數(shù)字,下文會講到)。

二. 實現(xiàn)思路
具體實現(xiàn)思路:
- 將input標簽相對于父元素做絕對定位,與父元素左邊距設(shè)置為負的本身寬度即可(position: absolute; top: 0; left:-100%; width: 100%; height: 100%;)。
- 動態(tài)去設(shè)置input的focus屬性。
- input同級使用for循環(huán)去創(chuàng)建5個正方形的view標簽。
- 給input同級創(chuàng)建的view標簽綁定點擊事件,在點擊事件方法實現(xiàn)中去設(shè)置input的focus屬性為true,即可彈出鍵盤。
- 在鍵盤輸入的時候,即可觸發(fā)input屬性的一系列方法,利用v-model雙向綁定,將input輸入的值賦值給循環(huán)的view方框即可。
- 這樣input也就不在屏幕中,但是又可以觸發(fā)input的事件。
總的來說就是,使用for循環(huán)去創(chuàng)建5個正方形的view標簽,然后創(chuàng)建一個input標簽,type=tel,最大輸入長度為5(根據(jù)需求來設(shè)置),再將input偽隱藏掉,獲取的值分別放到5個view中展示。
驗證碼失敗后利用v-model雙向綁定,清空輸入的值,增加錯誤提示文字和邊框樣式。
三. 代碼實現(xiàn)
父組件
<uni-popup ref="codeInputPopup" background-color="#fff" :mask-click ="false" type="center">
<CodeInput
:codeLength="5"
:disabled="codeBtnDisabled"
@codeInputClose="codeInputClose"
@submitGoodCode="submitGoodCode"
/>
</uni-popup>
<script>
export default {
data() {
return {
intviation_code:'', //邀請碼
codeBtnDisabled: false //防止接口請求還未返回數(shù)據(jù),用戶多次點擊
}
},
methods: {
// 提交邀請碼
async submitGoodCode(intviation_code){
this.codeBtnDisabled = true
this.intviation_code = intviation_code
const response = await this.$api.post('/ebapi/pink_api/secret_intviation_check', {
code: intviation_code
})
if(response.code === 200){
this.codeBtnDisabled = false
this.$refs.codeInputPopup.close()
}else{
this.codeBtnDisabled = false
this.$refs.codeInputPopup.close()
this.$api.msg(response.msg)
}
},
codeInputClose(){
this.$refs.codeInputPopup.close()
this.codeBtnDisabled = false
}
}
</script>子組件
<template>
<view>
<view class="code-popup-top">
<view class="code-title">請輸入商品邀請碼</view>
<view class="close-icon" @click="codeInputClose">
<uni-icons type="closeempty" size="30" color="#999999" />
</view>
</view>
<!-- 錯誤提示 -->
<view class="code_errow" v-if="codeColor == '#ff0000'&& !isNum">邀請碼必須{{ codeLength }}位數(shù)</view>
<view class="code_errow" v-if="codeColor == '#ff0000'&& isNum ">邀請碼必須是數(shù)字</view>
<view class="code_input_con">
<view
v-for="(item, index) in codeLength"
:key="index"
class="code_input_item"
:style="(index == intviation_code.length? 'border: 5rpx solid #1195db; width: 88rpx; height: 88rpx; line-height: 80rpx;':'color: ' + codeColor + ';' +'border: 2rpx solid' + codeColor)"
@click="focus = true"
>{{ intviation_code[index] && intviation_code[index] || '' }}</view>
<input
class="cinput"
type="tel"
v-model="intviation_code"
:maxlength="codeLength"
:focus="focus"
:cursor="intviation_code.length"
@focus="focus = true "
@blur="focus = false"
/>
</view>
<button
:class="['submit_code_btn', disabled ? 'btn_disabled' : '']"
:disabled="disabled"
@click="submitGoodCode"
>確定</button>
</view>
</template>
<script>
export default {
data() {
return {
codeColor: '#313131', //自定義錯誤碼顏色
intviation_code: '', //用戶輸入的驗證碼
focus: false, // 動態(tài)獲取焦點的值
isNum: false,
}
},
props: {
codeLength: {
type: Number,
default: 5,
},
disabled: {
type: Boolean,
default: false,
},
},
methods: {
codeInputClose() {
this.intviation_code = ''
this.$emit('codeInputClose')
},
submitGoodCode() {
if (this.intviation_code.length === this.codeLength) {
if (Number(this.intviation_code)) {
this.$emit('submitGoodCode', this.intviation_code)
} else {
this.isNum = true
this.publicErrorSetting()
}
} else {
this.publicErrorSetting()
}
},
// 輸入不符合規(guī)范,更改樣式并清空
publicErrorSetting() {
this.codeColor = '#ff0000'
setTimeout(() => {
this.intviation_code = ''
this.codeColor = '#313131'
this.isNum = false
}, 1000)
},
},
}
</script>
<style lang="scss" scoped>
.code-popup-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 50upx;
.code-title {
font-size: 34upx;
color: #333;
font-weight: bold;
position: relative;
&::before {
content: '';
position: absolute;
bottom: 0;
width: 40upx;
height: 19upx;
background: linear-gradient(
to right,
rgba(57, 181, 74, 1),
rgba(57, 181, 74, 0.1)
);
}
}
.close-icon {
background: #f2f4f7;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
}
.code_errow {
font-size: 30upx;
color: #ff5500;
margin-bottom: 20upx;
}
.submit_code_btn {
width: 100%;
height: 83upx;
line-height: 83upx;
border-radius: 7upx;
background: #39b54a;
color: #fff;
font-size: 31upx;
text-align: center;
margin-top: 45upx;
}
.btn_disabled {
color: rgba(255, 255, 255, 0.5) !important;
background-color: rgba(57, 181, 74, 0.4) !important;
}
.code_input_con {
display: flex;
justify-content: space-around;
position: relative;
.code_input_item {
margin-left: 10upx;
text-align: center;
line-height: 88upx;
border-radius: 14upx;
width: 88upx;
height: 88upx;
font-size: 60upx;
font-weight: bold;
color: #333;
&:last-child {
margin-right: 0;
}
}
/*input隱藏掉*/
.cinput {
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
}
}
</style>
四. 過程中遇到的問題
1)input 的type=‘number’, ios手機正常,光標在內(nèi)容最后,但Android手機光標有時候在內(nèi)容最前面,導(dǎo)致聚焦內(nèi)容刪不掉。
修改input 的type = 'tel',:cursor="intviation_code.length", 這樣cursor屬性才生效,并指定focus時光標的位置在內(nèi)容最后;
type=‘tel’,也會有個小問題,可以輸入一些字符,但是我們的需求只能是數(shù)字,所以代碼中要做限制。就能解決這個問題了。
這個cursor無效的問題,在h5模式應(yīng)該是type的原因,我試了在type是number或digit時cursor就無效,text、tel、idcard就有效
2)還有另外一種方法
- 設(shè)置input的type=“number”,就不需要設(shè)置光標位置了;然后隱藏input文字和光標,相當于間接隱藏了input框;
- 用到了css樣式設(shè)置,
color: transparent; caret-color: transparent; - 最主要的還是相對于父元素做絕對定位,與父元素左邊距設(shè)置為負的本身寬度的一半即可(position: absolute; top: 0; left:-100%; width: 200%; height: 100%;)with: 200%為了增大點擊區(qū)域,解決Android機型再次喚起鍵盤不能聚焦,刪不掉錯誤數(shù)字的問題。
<template>
<view>
<input
class="cinput"
type="number"
v-model="intviation_code"
:maxlength="codeLength"
:focus="focus"
@focus="focus = true "
@blur="focus = false"
/>
</view>
</view>
</template>
<script>
export default {
data() {
return {
intviation_code: '', //商品邀請碼
focus: false,
}
},
methods: {}
</script>
<style lang="scss" scoped>
.cinput {
position: absolute;
top: 0;
left: -100%;
width: 200%;
height: 100%;
color: transparent; //輸入文字顏色透明
caret-color: transparent !important; //改變插入光標顏色為透明
}
}
// 考慮兼容性
// 瀏覽器支持caret-color屬性,優(yōu)先使用caret-color(Chrome/Firefox/Opera);其次使用::first-line方法(Safari);最后忽略(如IE)。
@supports (-webkit-mask: none) and (not (caret-color: transparent)) {
.cinput {
color: transparent !important;
}
.cinput::first-line {
color: transparent !important;
}
}
</style>
還可參考:
6位驗證碼輸入框、隱藏光標、letter-spacing失效、自定義光標,光標動畫
uniapp 手機驗證碼輸入框(隨機數(shù)、倒計時、隱藏手機號碼中間四位)可以直接使用
到此這篇關(guān)于uniapp自定義驗證碼輸入框,隱藏光標的文章就介紹到這了,更多相關(guān)uniapp驗證碼輸入框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript Ajax異步讀取RSS文檔具體實現(xiàn)
這篇文章主要介紹了Javascript Ajax異步讀取RSS文檔具體實現(xiàn),有需要的朋友可以參考一下2013-12-12
詳談for循環(huán)里面的break和continue語句
下面小編就為大家?guī)硪黄斦刦or循環(huán)里面的break和continue語句。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
JS驗證日期的格式Y(jié)YYY-mm-dd 具體實現(xiàn)
這篇文章介紹了JS對日期格式的驗證實例,有需要的朋友可以參考一下2013-06-06
理解JAVASCRIPT中hasOwnProperty()的作用
JavaScript中hasOwnProperty函數(shù)方法是返回一個布爾值,指出一個對象是否具有指定名稱的屬性2013-06-06
JavaScript中數(shù)據(jù)過濾的幾種常見方法
JavaScript是一種廣泛使用的編程語言,它提供了多種方法來對數(shù)據(jù)進行過濾,在本文中,我們將介紹JavaScript中常見的幾種數(shù)據(jù)過濾方法,并提供相應(yīng)的示例,感興趣的朋友跟隨小編一起看看吧2023-10-10
JS新標簽頁打開的方法大全(讓你的網(wǎng)站訪問更加便捷)
在開發(fā)Web應(yīng)用中我們常常需要在當前頁面打開一個鏈接,但又不希望離開當前頁面,這篇文章主要給大家介紹了關(guān)于JS新標簽頁打開的方法大全,通過這些方法可以讓你的網(wǎng)站訪問更加便捷,需要的朋友可以參考下2023-10-10
KnockoutJS 3.X API 第四章之數(shù)據(jù)控制流if綁定和ifnot綁定
這篇文章主要介紹了KnockoutJS 3.X API 第四章之數(shù)據(jù)控制流if綁定和ifnot綁定的相關(guān)資料,需要的朋友可以參考下2016-10-10
微信小程序scroll-view實現(xiàn)橫向滾動和上拉加載示例
本篇文章主要介紹了微信小程序scroll-view實現(xiàn)橫向滾動和上拉加載示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
JavaScript Promise原理與實現(xiàn)刨析
首先呢,Promise是異步中比較重要的知識點,學習的最好方法就是掌握它的基本原理。所以這一篇主要說一下如何用JS來實現(xiàn)一個自己的promise2022-10-10
微信小程序動態(tài)設(shè)置導(dǎo)航欄標題的實現(xiàn)步驟
實際開發(fā)中很多時候我們需要通過上個頁面?zhèn)鬟^來的值動態(tài)的更改標題欄文字,下面這篇文章主要給大家介紹了關(guān)于微信小程序動態(tài)設(shè)置導(dǎo)航欄標題的實現(xiàn)步驟,需要的朋友可以參考下2023-02-02

