uniapp实现自定义验证码输入框

291 阅读1分钟

一、实现效果

image.png

二、实现代码

<view class="code__main flex justify-between">
    <!-- 该部分展示给用户- -->
    <view 
      v-for="(n, idx) in code.total"
      :key="n" 
      :class="['code__small-box', { 'code__active': !!code.list[idx] }]"
      @click="onClick(idx)"
    >
      <view :class="[{ 'code__focus-move':  code.curIdx == n  || (isFocus && code.list.length == idx) }]">
       {{ code.curIdx == n ? null : code.list[idx] }}
      </view>
    </view>
    <!-- 输入框隐藏 -->
    <input 
      class="code__hide-input" 
      v-model="code.inputVal" 
      type="text" 
      maxlength="6" 
      :focus="focusInput"
      @focus="onFocus"
      @blur="onBlur"
      @input="onInput"
    >
</view>

<script setup>
import { ref, reactive } from 'vue'
const code = reactive({
  total: 6,
  curIdx: 0,
  inputVal: '',
  list: []
})

function onClick(idx) {
  focusInput.value = true
}

function onBlur() {
  focusInput.value = false
}

/**
 * 聚焦考试码
 */
function onFocus() {
  isFocus.value = true
  code.curIdx = code.inputVal.length + 1
}

/**
 * 输入考试码
 */
function onInput(e) {
  code.curIdx = e.detail.cursor + 1  // 判断当前光标所处下标
  code.list = code.inputVal.split('')
  if (code.total === code.list.length) {
     // 输入完毕,开始验证
  }
}
</script>

<style lang="scss" scoped>
.code {

  &__main {
    position: relative;
    width: 576rpx;
    margin: 66rpx auto;
  }

  &__small-box {
    position: relative;
    box-sizing: border-box;
    margin: 0 12rpx;
    width: 80rpx;
    height: 112rpx;
    line-height: 112rpx;
    text-align: center;
    color: #000;
    font-size: 48rpx;
    background-color: #fff;
    border: 2rpx solid #fff;
    border-radius: 16rpx;
    transition: border 0.3s;
  }

  &__hide-input {
    position: absolute;
    right: 99999px;
    z-index: 1;
    width: 1rpx;
    height: 1rpx;
    min-height: 1rpx;
    color: #fff;
    caret-color: none;
    background-color: none;
    outline: none;
  }
  
  &__hide-input:focus {
    color: #fff;
    outline: none;
    caret-color: none;
    background-color: none;
  }

  &__focus-move {
    position: absolute;
    top: 35rpx;
    left: 38rpx;
    height: 50rpx;
    width: 4rpx;
    background-color: #3C9CFF;
  }

  &__active {
    border: 2rpx solid #3C9CFF !important;
  }
}
</style>

三、过程遇到的坑

  • 问题过程:隐藏输入框使用方案width: 0px时, 会出现Andorid机型无法唤起键盘;
  • 解决方案:width至少为0.1px + 定位right:-99999px