微信小程序数字验证码组件

使用的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>

 效果如图

 

posted @ 2023-10-08 16:04  wayne529  阅读(216)  评论(0编辑  收藏  举报