uniapp自定義驗(yàn)證碼輸入框并隱藏光標(biāo)
目錄
- 一. 前言
- 二. 實(shí)現(xiàn)思路
- 三. 代碼實(shí)現(xiàn)
- 四. 過程中遇到的問題
一. 前言
先看下使用場景效果圖:
- 點(diǎn)擊輸入框喚起鍵盤,藍(lán)框就相當(dāng)于input的光標(biāo),驗(yàn)證碼輸入錯(cuò)誤或者不符合格式要求會(huì)將字體以及邊框改成紅色提示,持續(xù)1s,然后清空數(shù)據(jù),恢復(fù)原邊框樣式;
- 5位驗(yàn)證碼輸入完畢,點(diǎn)擊頁面其他位置,隱藏鍵盤;這時(shí)如果發(fā)現(xiàn)驗(yàn)證碼有誤,再次點(diǎn)擊輸入框又喚起鍵盤,也能正常刪除數(shù)字(這里其實(shí)做的時(shí)候遇到了bug,再次聚焦不能刪除錯(cuò)誤數(shù)字,下文會(huì)講到)。
二. 實(shí)現(xiàn)思路
具體實(shí)現(xiàn)思路:
- 將input標(biāo)簽相對于父元素做絕對定位,與父元素左邊距設(shè)置為負(fù)的本身寬度即可(position: absolute; top: 0; left:-100%; width: 100%; height: 100%;)。
- 動(dòng)態(tài)去設(shè)置input的focus屬性。
- input同級使用for循環(huán)去創(chuàng)建5個(gè)正方形的view標(biāo)簽。
- 給input同級創(chuàng)建的view標(biāo)簽綁定點(diǎn)擊事件,在點(diǎn)擊事件方法實(shí)現(xiàn)中去設(shè)置input的focus屬性為true,即可彈出鍵盤。
- 在鍵盤輸入的時(shí)候,即可觸發(fā)input屬性的一系列方法,利用v-model雙向綁定,將input輸入的值賦值給循環(huán)的view方框即可。
- 這樣input也就不在屏幕中,但是又可以觸發(fā)input的事件。
總的來說就是,使用for循環(huán)去創(chuàng)建5個(gè)正方形的view標(biāo)簽,然后創(chuàng)建一個(gè)input標(biāo)簽,type=tel,最大輸入長度為5(根據(jù)需求來設(shè)置),再將input偽隱藏掉,獲取的值分別放到5個(gè)view中展示。
驗(yàn)證碼失敗后利用v-model雙向綁定,清空輸入的值,增加錯(cuò)誤提示文字和邊框樣式。
三. 代碼實(shí)現(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 //防止接口請求還未返回?cái)?shù)據(jù),用戶多次點(diǎn)擊 } }, 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> <view>請輸入商品邀請碼</view> <view @click="codeInputClose"><uni-icons type="closeempty" size="30" color="#999999" /> </view> </view> <!-- 錯(cuò)誤提示 --> <view v-if="codeColor == "#ff0000"&& !isNum">邀請碼必須{{ codeLength }}位數(shù)</view> <view v-if="codeColor == "#ff0000"&& isNum ">邀請碼必須是數(shù)字</view> <view> <viewv-for="(item, index) in codeLength":key="index" :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 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", //自定義錯(cuò)誤碼顏色 intviation_code: "", //用戶輸入的驗(yàn)證碼 focus: false, // 動(dòng)態(tài)獲取焦點(diǎn)的值 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手機(jī)正常,光標(biāo)在內(nèi)容最后,但Android手機(jī)光標(biāo)有時(shí)候在內(nèi)容最前面,導(dǎo)致聚焦內(nèi)容刪不掉。
修改input 的type = 'tel'
,:cursor="intviation_code.length"
, 這樣cursor屬性才生效,并指定focus時(shí)光標(biāo)的位置在內(nèi)容最后;
type=‘tel’,也會(huì)有個(gè)小問題,可以輸入一些字符,但是我們的需求只能是數(shù)字,所以代碼中要做限制。就能解決這個(gè)問題了。
這個(gè)cursor無效的問題,在h5模式應(yīng)該是type的原因,我試了在type是number或digit時(shí)cursor就無效,text、tel、idcard就有效
2)還有另外一種方法
- 設(shè)置input的type=“number”,就不需要設(shè)置光標(biāo)位置了;然后隱藏input文字和光標(biāo),相當(dāng)于間接隱藏了input框;
- 用到了css樣式設(shè)置,
color: transparent; caret-color: transparent;
- 最主要的還是相對于父元素做絕對定位,與父元素左邊距設(shè)置為負(fù)的本身寬度的一半即可(position: absolute; top: 0; left:-100%; width: 200%; height: 100%;)with: 200%為了增大點(diǎn)擊區(qū)域,解決Android機(jī)型再次喚起鍵盤不能聚焦,刪不掉錯(cuò)誤數(shù)字的問題。
<template> <view> <input 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; //改變插入光標(biāo)顏色為透明 } } // 考慮兼容性 // 瀏覽器支持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位驗(yàn)證碼輸入框、隱藏光標(biāo)、letter-spacing失效、自定義光標(biāo),光標(biāo)動(dòng)畫
uniapp 手機(jī)驗(yàn)證碼輸入框(隨機(jī)數(shù)、倒計(jì)時(shí)、隱藏手機(jī)號碼中間四位)可以直接使用
到此這篇關(guān)于uniapp自定義驗(yàn)證碼輸入框,隱藏光標(biāo)的文章就介紹到這了,更多相關(guān)uniapp驗(yàn)證碼輸入框內(nèi)容請搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!
