Я работаю над компонентом в приложении vue, которое принимает код доступа, состоящий из 8 цифр, каждая цифра имеет свой собственный ввод при вводе символа, он должен перейти к следующему вводу, если пользователь удаляет символ, если он может, фокус должен перейти к предыдущему брату, если пользователь нажимает левую или правую клавишу, фокус должен перемещаться вместе с нажатием клавиши. На данный момент происходит то, что события @input и @keydown запускаются, поэтому, если пользователь нажимает влево, а предыдущий брат уже имеет контент, он перемещает фокус обратно вправо.

Вот мой код,

<div class="code">
  <input autofocus type="text" maxlength="1" class="passcode__box" @input="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @input="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
  <input type="text" class="passcode__box" maxlength="1" @keyup="handleInput" @keydown="handleKeyDown"/>
</div>

И 2 метода,

handleInput(event) {
  const value = event.target.value;
  const nextElement = event.target.nextElementSibling;
  if (value === "" || !nextElement) {
    return;
  }
  nextElement.focus();

},

  handleKeyDown(event) {
    console.log('handleKeyDown');
    //Right arrow key
    if(event.keyCode == 39) {
      event.target.nextElementSibling.focus();
    }

    //Left arrow key
    if(event.keyCode == 37) {
      event.target.previousElementSibling.focus();
    }

    //Backspace key - cmd
    if(event.keyCode == 8) { //backspace
      if(event.target.value === '') {
        event.target.previousElementSibling.focus();
        return;
      }
      event.target.value = '';
    }
  }

Вот пример компонента, который странным образом использует тот же код введите здесь описание ссылки

3
Udders 2 Ноя 2019 в 23:32

1 ответ

Я предполагаю, что проблема в событиях @keyup, потому что @keyup испускается после @input. Подробнее о KeyboardEvents и их последовательностях можно прочитать в этой статье MDN.

В любом случае, я позволил себе переписать/рефакторинг кода, который вы предоставили, и представил пару JS-махинаций. Хотя идея та же. Существует рабочий пример в CodeSandbox.

Надеюсь, это помогло!

<template>
  <div class="passcode">
    <template v-for="index in inputs">
      <input
        type="text"
        class="passcode__box"
        :key="index"
        :maxlength="maxlength"
        @keydown="onKeydown"
        @input="onInput"
      >
    </template>
  </div>
</template>
<script>
export const KeyCodes = {
  RIGHT_ARROW: 39,
  LEFT_ARROW: 37,
  BACKSPACE: 8
};

export default {
  name: "Passcode",

  props: {
    inputs: {
      type: Number,
      default: 4
    },
    maxlength: {
      type: Number,
      default: 1
    }
  },

  methods: {
    /**
     * Moves focus between siblings and handles `Backspace`.
     *
     * @param {KeyboardEvent} event
     */
    onKeydown(event) {
      const target = event.target;
      const next = target.nextElementSibling;
      const prev = target.previousElementSibling;

      switch (event.keyCode) {
        case KeyCodes.RIGHT_ARROW:
          next && next.focus();
          break;

        case KeyCodes.LEFT_ARROW:
          prev && prev.focus();
          break;

        case KeyCodes.BACKSPACE:
          if (target.value.length) {
            target.value = "";
            return;
          }

          setTimeout(() => prev && prev.focus());
          break;

        default:
          break;
      }
    },

    /**
     * Handles printable characters and moves focus
     * to the next <input> sibling if it's present.
     *
     * @param {KeyboardEvent} event
     */
    onInput(event) {
      const value = event.target.value;
      const next = event.target.nextElementSibling;

      if (!value.length || !next) {
        return;
      }

      next.focus();
    }
  }
};
</script>
0
user12312412user12312412 3 Ноя 2019 в 04:22