写登录注册功能时, 在一个输入框输入完毕后, 习惯性按下 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')
}
}