先看下使用场景效果图:
具体实现思路:
总的来说就是,使用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> <view v-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)还有另外一种方法
color: transparent; caret-color: transparent;
<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验证码输入框内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!