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