【问题标题】:@keydown and @input firing together@keydown 和 @input 一起触发
【发布时间】:2020-02-28 16:25:12
【问题描述】:

我正在开发一个 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>

还有两种方法,

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 = '';
    }
  }

这是一个组件示例,它奇怪地使用了相同的代码enter link description here

【问题讨论】:

    标签: javascript html vue.js


    【解决方案1】:

    我猜问题出在@keyup 事件中,因为@keyup@input 之后发出。您可以在this MDN article 中阅读有关键盘事件及其序列的更多信息。

    无论如何,我冒昧地重写/重构了您提供的代码,并引入了一些 JS 恶作剧。这个想法是一样的。有一个工作示例on 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多