Используйте VUE, чтобы написать компонент ввода кода подтверждения за считанные минуты.

Vue.js
Используйте VUE, чтобы написать компонент ввода кода подтверждения за считанные минуты.

Эффект

Первый взгляд на визуализацию завершения волны

效果图

адрес предварительного просмотра

гитхаб-адрес

Адрес NPM

нужно

Введите 4-значный или 6-значный SMS-код подтверждения и уберите клавиатуру после завершения ввода.

Этапы реализации

первый шаг

макет

<div class="security-code-wrap">
    <label for="code">
      <ul class="security-code-container">
        <li class="field-wrap" v-for="(item, index) in number" :key="index">
          <i class="char-field">{{value[index] || placeholder}}</i>
        </li>
      </ul>
    </label>
    <input ref="input" class="input-code" @keyup="handleInput($event)" v-model="value"
           id="code" name="code" type="tel" :maxlength="number"
           autocorrect="off" autocomplete="off" autocapitalize="off">
</div>
  • Используйте элемент li для имитации отображения поля ввода, другой цели нет, просто для семантики, конечно, вы также можете использовать для имитации любой другой элемент, например div.
  • Преимущество использования тега label в том, что его можно ассоциировать с событием клика ввода, с одной стороны, он реализует семантическое решение, а с другой избавляет нас от вызова виртуальной клавиатуры через js.

скрыть поле ввода

.input-code {
    position: absolute;
    left: -9999px;
    top: -9999px;
}
  • Расположите реальное поле ввода за пределами видимой области экрана, и при вызове виртуальной клавиатуры страница не будет проталкиваться вверх. Поэтому ваш компонент ввода кода подтверждения должен быть размещен в месте, где виртуальная клавиатура не может быть заблокирована.

второй шаг

Обработка ввода капчи

handleSubmit () {
  this.$emit('input', this.value)
},
handleInput (e) {
  if (e.target.value.length >= this.length) {
    this.hideKeyboard()
  }
  this.handleSubmit()
}
  • При вводе присвоение значения полю ввода - это решение проблемы перефокусировки поля ввода на стороне андроида после того, как оно не в фокусе.

третий шаг

Закройте виртуальную клавиатуру, когда закончите печатать.

hideKeyboard() {
  // 输入完成隐藏键盘
  document.activeElement.blur() // ios隐藏键盘
  this.$refs.input.blur() // android隐藏键盘
}

Полный код компонента

<template>
  <div class="security-code-wrap">
    <label :for="`code-${uuid}`">
      <ul :class="`${theme}-container security-code-container`">
        <li class="field-wrap" v-for="(item, index) in length" :key="index">
          <i class="char-field">{{value[index] || placeholder}}</i>
        </li>
      </ul>
    </label>
    <input ref="input" class="input-code" @keyup="handleInput($event)" v-model="value"
           :id="`code-${uuid}`" :name="`code-${uuid}`" type="tel" :maxlength="length"
           autocorrect="off" autocomplete="off" autocapitalize="off">
  </div>
</template>

<script>
  export default {
    name: 'SecurityCode',
    // component properties
    props: {
      length: {
        type: Number,
        default: 4
      },
      placeholder: {
        type: String,
        default: '-'
      },
      theme: {
        type: String,
        default: 'block'
      }
    },
    // variables
    data () {
      return {
        value: ''
      }
    },
    computed: {
      uuid () {
        return Math.random().toString(36).substring(3, 8)
      }
    },
    methods: {
      hideKeyboard () {
        // 输入完成隐藏键盘
        document.activeElement.blur() // ios隐藏键盘
        this.$refs.input.blur() // android隐藏键盘
      },
      handleSubmit () {
        this.$emit('input', this.value)
      },
      handleInput (e) {
        if (e.target.value.length >= this.length) {
          this.hideKeyboard()
        }
        this.handleSubmit()
      }
    }
  }
</script>

<style scoped lang="less">
  .security-code-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .security-code-container {
    margin: 0;
    padding: 0;
    display: flex;
    .field-wrap {
      list-style: none;
      display: block;
      height: 40px;
      width: 40px;
      line-height: 40px;
      font-size: 16px;
      .char-field {
        font-style: normal;
      }
    }
  }

  .block-container {
    justify-content: center;
    .field-wrap {
      background-color: #fff;
      margin: 2px;
      color: #000;
    }
  }

  .line-container {
    position: relative;
    background-color: #fff;
    &:after {
      box-sizing: border-box;
      content: "";
      width: 200%;
      height: 200%;
      transform: scale(.5);
      position: absolute;
      border: 1px solid #d9d9d9;
      top: 0;
      left: 0;
      transform-origin: 0 0;
      border-radius: 4px;
    }
    .field-wrap {
      flex: 1;
      position: relative;
      &:not(:last-child):after {
        content: "";
        width: 1px;
        height: 50%;
        position: absolute;
        right: 0;
        top: 25%;
        background-color: #d9d9d9;
        transform: scaleX(.5);
      }
    }
  }

  .input-code {
    position: absolute;
    left: -9999px;
    top: -9999px;
  }

</style>

код использования компонента

<security-code v-model="code"></security-code>

заключительные замечания

как, 484 так просто

Идея в начале также состоит в том, чтобы иметь 4 поля ввода, отслеживать ввод и переходить к следующему полю ввода, этот подход также может достичь цели, но для поддержания этого правила требуется больше кода, что не является элегантным.

Текущий подход уже является лучшим решением, о котором я могу думать. Если у вас есть лучшая идея реализации, я надеюсь, что вы можете дать мне несколько советов.

адрес предварительного просмотра

гитхаб-адрес

адрес нпм