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