写登录注册功能时, 在一个输入框输入完毕后, 习惯性按下 Enter 键来切换到下一个输入框, 但是此时这个功能我还没有实现...emm

尝试一(搁浅)

既然 Tab 键可以切换焦点, 那么将 Tab 键的功能转接到 Enter 键上不就好了嘛, 也就是表面按下的是 Enter 键, 但 "实际" 按下的是 Tab 键, 于是试图通过人造事件 (synthetic events) 来实现.

创建与触发事件: https://developer.mozilla.org...

父组件: (在这个尝试中没排上用场, 可以不看)

<template>     <div id="login-box">     <mo-form class="login-form">      <mo-form-item>        <mo-input          type="text"           text="用户名"           v-model="loginInfo.username"               ></mo-input>              </mo-form-item>      <mo-form-item>        <mo-input          type="password"           text="密码"           v-model="loginInfo.password"                  ></mo-input>              </mo-form-item>          </mo-form>  </div>    </template>

子组件 mo-input : (看最后四个键盘事件监听即可)

<template>  <div class="mo-input">    <span class="text">{{text}}: </span>    <input :type="type" class="input"      :class="{focused: isFocused}"                 @focus="isFocused = true" @blur="isFocused = false"      :value="value"      @change="$emit('change', $event.target.value)"      @keyup.enter.prevent="moveFocus"          @keydown.tab="tabClick"      @keypress.tab="tabClick"      @keyup.tab="tabClick"      >     </div></template>
methods: {// moveFocus 方法监听在 input 输入框中按下 Enter 键    moveFocus(e){         console.log(e)      const key = {        key: 'Tab',        code: 'Tab',        keyCode: '9'      }      const e1 = new KeyboardEvent('keydown', key)      const e2 = new KeyboardEvent('keypress', key)      const e3 = new KeyboardEvent('keyup', key)      e.currentTarget.dispatchEvent(e1)          e.currentTarget.dispatchEvent(e2)          e.currentTarget.dispatchEvent(e3)     },    tabClick(e){      console.log(e)      console.log(e.currentTarget)      console.log('tabClick')    }}

在第一个输入框中按下 Enter 键:

结果: 三个事件均发送成功, 并可以成功监听, 但是并没有出现 Tab 键切换焦点的效果.


接着, 按 Tab 键:

结果: 第一个输入框发生 keydown 事件; 第二输入框发生 keyup 事件. 也就是之前的想法是错的, 按下 Tab 键并不是触发了三个事件

这个不知道怎么模拟, 使用另一个感觉简单一些的按键 -- 字母 A 键 -- 试一试

//修改事件监听@keyup.enter.prevent="moveFocus"    @keydown="aClick"@keypress="aClick"@keyup="aClick"  //修改 moveFocus 方法中的 key 对象const key = {  key: 'a',  code: 'KeyA',  keyCode: '65'}//修改事件处理函数aClick(e){  if(e.key == 'a'){    console.log(e)    console.log(e.currentTarget)    console.log('aClick')   }}

结果: 正常按下 A 键会发生 keydown, keypress, keyup 事件, 但是反过来按下 Enter 键人工触发这三个事件并不会在输入框中 "写出" a, 要自己在事件处理函数中为 e.currentTarget.value 赋值才行

aClick(e){  if(e.key == 'a' && e.type == "keyup"){           e.currentTarget.value += e.key  }      }

目前看来, 这条路走不通.

尝试二(成功)

找到当前聚焦的元素和下一个要聚焦的元素, 使用 focus()
在输入框中按下 Enter 键后发送自定义事件到父组件; 父组件通过 ref 获取 mo-form 组件实例, 该实例的 $el 属性中最前面的数字键值对, 就是可聚焦的元素 (console.dir 可以看到, console.log 打印出 DOM 结构)

父组件:

<template>     <div id="login-box">     <mo-form class="login-form" ref="formRef">      <mo-form-item>        <mo-input          type="text"           text="用户名"           v-model="loginInfo.username"          @moveFocus="moveFocus"          ></mo-input>              </mo-form-item>      <mo-form-item>        <mo-input          type="password"           text="密码"           v-model="loginInfo.password"                  ></mo-input>              </mo-form-item>          </mo-form>  </div>    </template>
methods: {   // moveFocus 方法实现焦点切换    moveFocus(){       const form = this.$refs.formRef      const active = document.activeElement      let flag = true      let key = 0      while(flag){        if(form.$el[key] == active){          flag = false                   form.$el[key + 1].focus()        }else{          key ++        }      }    }}

mo-input 子组件:

<template>  <div class="mo-input">    <span class="text">{{text}}: </span>    <input :type="type" class="input"      :class="{focused: isFocused}"                 @focus="isFocused = true" @blur="isFocused = false"      :value="value"      @change="$emit('change', $event.target.value)"      @keyup.enter.prevent="moveFocus"           >     </div></template>
methods: {// moveFocus 方法监听在 input 输入框中按下 Enter 键  moveFocus(e){       this.$emit('moveFocus')  }}