微信小程序数字验证码组件
使用的uniapp开发的小程序,搭载的vue3的项目
html部分
1.实际输入框绝对定位并盖在显示的内容框上
2.内容框仅为显示,分别取实际输入框字符对应的索引的值,即第一个框则显示第一个字,依次类推
3.进入页面自动对焦使用input的focus="true"的属性
<template> <div class="dialog-container"> <div class="input-container"> <div class="input-tip"> 为保护客户的隐私安全,请输入快递预留的 </div> <div class="input-title"> 收/寄件人联系方式的后四位 </div> <div class="input-tip"> 进行验证 </div> <div class="input-list"> <input ref="inputCodeRef" v-model="inputCode" class="input-opacity" type="number" placeholder="" maxlength="4" :focus="true" > <div v-for="(item, index) in inputItems" :key="index" :class="['input-item', { 'is-active': index === inputIndex }]" > {{ inputValues[index] ? inputValues[index] : '' }} </div> </div> </div> </div> </template>
js部分
1.监听实际输入框的值,完成则emit回调事件
2.显示的内容根据实际输入框依次取值
<script> import { ref, defineComponent, watch, nextTick, computed, onMounted } from 'vue' export default defineComponent({ name: 'VerifyCode', setup(props, { emit }) { const show = ref(true) const inputItems = ref(new Array(4).fill('')) const inputCode = ref('') const inputIndex = computed(() => { return inputCode.value.length - 1 }) const inputValues = computed(() => { return inputCode.value.split('') }) watch(inputCode, () => { console.log(inputCode.value) if (inputCode.value.length === 4) { console.log('finish') emit('finish', inputCode.value) } }) return { show, inputCode, inputItems, inputIndex, inputValues, } }, }) </script>
css部分
1.由于小程序的input框无法设置为透明,光标也无法设置为透明,故使用了hack的方式,将输入框拉长到2倍以上,并且容器overflow:hidden。这样错位的方式便可遮蔽了输入内容和光标,用户看到的是用于展示的内容值的几个方块格子
<style lang="scss"> .input-list { position: relative; display: flex; justify-content: center; margin: 10rpx; overflow: hidden; } .input-opacity { position: absolute; display: block; width: 240%; height: 100%; left: -140%; right: 0; top: 0; bottom: 0; opacity: 0; color: transparent; // color: #000000; font-size: 54rpx; line-height: 54rpx; letter-spacing: 32rpx; text-align: left; } .input-item { display: flex; width: 108rpx; height: 108rpx; box-sizing: border-box; border-bottom: 4rpx solid #dcdfe6; margin: 0 16rpx; align-items: center; justify-content: center; color: #333333; font-family: PingFang SC; font-size: 54rpx; line-height: 54rpx; text-align: center; &.is-active { border-bottom: 4px solid #d41424; } } .dialog-container { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: rgba($color: #000000, $alpha: 0.8); } .input-container { border-radius: 4px; background: #ffffff; padding: 64rpx 53rpx; text-align: center; width: 638rpx; box-sizing: border-box; margin: 80rpx auto; .input-tip { opacity: 1; color: #666666; font-family: PingFang SC; font-weight: regular; font-size: 28rpx; line-height: 28rpx; text-align: center; margin-bottom: 32rpx; } .input-title { opacity: 1; color: #333333; font-family: PingFang SC; font-weight: medium; font-size: 28rpx; line-height: 28rpx; letter-spacing: 0rpx; text-align: center; margin-bottom: 32rpx; font-weight: bold; } } </style>
效果如图