Vue中怎么实现回车键切换焦点
这篇文章主要介绍了Vue中怎么实现回车键切换焦点,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
vue是什么
Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框架的区别是,使用Vue可以自底向上逐层应用,其核心库只关注视图层,方便与第三方库和项目整合,且使用Vue可以采用单文件组件和Vue生态系统支持的库开发复杂的单页应用。
几乎在所有浏览器中,都具有 Tab 键切换焦点的功能。
但是任性的用户强烈要求一定要有 Enter 键切换焦点的功能。
为了交付上线拿到钱,我们只好再一次毫无原则性的接受了客户的需求。
在上一代人中,大多都有这种操作习惯。习惯把保存成为编辑,习惯用回车替换 Tab。这是受到微软 excel 荼毒的结果。
起初我以为这个功能很简单,无非就是把 Enter 键的功能转接到 Tab 键上面,分分钟就可以解决掉的问题。
可困难马上就出现了,我发现这条路是走不通的。
我们经常可以主动触发某个事件,比如 el.click()
就可以调用点击事件,或者使用 dispatchEvent
。但是键盘和鼠标事件却不行。
我查阅了很多资料,也做了很多尝试。最后总结出来一个结论,在浏览器中,JavaScript 无法操作用户的键盘或者鼠标,这是出于安全策略的考虑。仔细想一下,如果可以用一段 JavaScript 脚本控制用户键盘和鼠标的话,那么用户只需要打开一个黑客网站,黑客就可以瞬间得到他想得到的一切。
所以,如果要通过除 Tab 键以外的其他方式来触发焦点切换, focus
几乎是唯一的选择。
在原生页面中实现回车键切换焦点
项目是基于 vue 和 element-ui 做的,为了把实现思路先讲清楚,暂时把这些抛开,从原生的页面中寻找答案。
以下是一个原生的 html 页面。
<!DOCTYPEhtml> <html> <head> <metacharset="utf-8"/> <metaname="viewport"content="width=device-width"/> <title>Demo</title> </head> <body> <form> <inputplaceholder="姓名"/> <inputplaceholder="性别"/> <inputplaceholder="年龄"/> </form> </body> </html>
接下来要实现通过回车键切换焦点,我把思路梳理如下:
监听回车键按下事件。
获取当前聚焦元素。
获取下一个要被聚焦的元素。
切换焦点。
思路有了,实现起来也非常简单。
1.监听回车键按下事件
在文档中添加 script 标签,写入如下代码。
functionenterCallback(e){ if(e.keyCode===13){ //按下回车后的逻辑 } } window.addEventListener("keydown",enterCallback);
要注意, enterCallback
单独拿出来,用于注销监听事件。
监听按键事件最常用的方法就是使用事件委托,将事件绑定到 window
对象上。相比较给每一个元素都绑定一个事件的方式,这样做的最大好处就是节省内存空间,性能更好。
判断按下哪个键的方式有很多,比如判断 e.key
、 e.code
或者 e.keyCode
等方式。但绝大多数的情况下都建议使用 e.keyCode
。下面是一张来自网络的 keyCode
表。
2.获取当前聚焦元素
很容易就可以做到这一步。
常见的有两种方式。第一种是 e.target
,第二种是 document.activeElement
。这种情况下,个人更推荐使用第二种。
functionenterCallback(e){ if(e.keyCode===13){ letactiveEl=document.activeElement; } }
3.获取下一个要被聚焦的元素
这一步也比较容易。使用 el.nextElementSibling
API 即可获取。
functionenterCallback(e){ if(e.keyCode===13){ letactiveEl=document.activeElement; letnextEl=activeEl.nextElementSibling; } }
4.切换焦点
切换焦点调用 focus
即可实现。
functionenterCallback(e){ if(e.keyCode===13){ letactiveEl=document.activeElement; letnextEl=activeEl.nextElementSibling; nextEl&&nextEl.focus(); } }
至此一个最简单的 Demo 已经实现了,接下来看看项目中实际的情况。
在 element-ui 项目中实现回车键切换焦点
因为是使用组件开发,加上样式等因素,dom 节点并不像上面写的原生 Demo 那么简单,实际情况是多层嵌套的。下面是实际生成的代码结构。
<div class="el-form-itemel-form-item--small" > <labelfor="pactcode"class="el-form-item__label" >协议号</label > <divclass="el-form-item__content"> <divclass="el-inputel-input--small"> <!----> <input type="text" autocomplete="off" id="el-input" placeholder="未填写协议号" class="el-input__inner" /> <!----> </div> </div> </div>
可以看到,如果每一个输入框都是这种类型的嵌套结构,上面的方法是无法直接解决的。因为 nextElementSibling
API 只能找到下一个兄弟元素,而在这里 input 明显找不到下一个兄弟元素。
思路是,通过回溯的手段朝外层寻找,直到找到一个类名包含 el-form-item
和 el-form-item--small
的祖级元素,然后再从这个祖级元素的下一个兄弟元素中寻找类名包含 el-input__inner
的 input 元素。
所以要再写两个函数,分别是寻找组件元素的 findFormItem
和寻找 input 元素的 findInput
。
findFormItem:
functionfindFormItem(el){ constparent=el.parentElement; if(!parent)returndocument.body; if( parent.className.includes("el-form-item")&& parent.className.includes("el-form-item--small") ){ returnparent; } returnfindFormItem(parent); }
findInput:
functionfindInput(container){ letnextEl=container.nextElementSibling; if(!nextEl)return; letinput=nextEl.querySelector("input"); while(input.id==="el-select"){ nextEl=nextEl.nextElementSibling; if(!nextEl)return; input=nextEl.querySelector("input"); } if(input.className.includes("el-input__inner"))returninput; }
有了这两个函数以后,实现回车切换焦点就非常简单了。只需要执行两行代码。
constcontainer=findFormItem(document.activeElement); findInput(container)&&findInput(container).focus();
完整的代码大概是这样的。
在 methods
中声明三个方法。
methods:{ addEnterListener(){ if(window.__completeEnterBind__)return; window.addEventListener("keydown",this.enterCallback); window.__completeEnterBind__=true; }, removeEnterListener(){ window.removeEventListener("keydown",this.enterCallback); window.__completeEnterBind__=false; }, enterCallback(e){ functionfindFormItem(el){ constparent=el.parentElement; if(!parent)returndocument.body; if( parent.className.includes("el-form-item")&& parent.className.includes("el-form-item--small") ){ returnparent; } returnfindFormItem(parent); } functionfindInput(container){ letnextEl=container.nextElementSibling; if(!nextEl)return; letinput=nextEl.querySelector("input"); while(input.id==="el-select"){ nextEl=nextEl.nextElementSibling; if(!nextEl)return; input=nextEl.querySelector("input"); } if(input.className.includes("el-input__inner"))returninput; } if(e.keyCode===13){ constcontainer=findFormItem(document.activeElement); findInput(container)&&findInput(container).focus(); } } }
然后在 mounted
中添加回车监听和在 destroy
中移除回车键听。
mounted(){ this.addEnterListener(); }, destroy(){ this.removeEnterListener(); },
需要注意的是,项目是多标签页的形式,表单组件可能会被渲染多次,所以通过在 window 对象上添加一个 __completeEnterBind__
字段来确保回车换行事件正确绑定。
感谢你能够认真阅读完这篇文章,希望小编分享的“Vue中怎么实现回车键切换焦点”这篇文章对大家有帮助,同时也希望大家多多支持恰卡编程网,关注恰卡编程网行业资讯频道,更多相关知识等着你来学习!
推荐阅读
-
vue表格组件教程学习(vue proxytable只能在开发环境跨域吗)
vueproxytable只能在开发环境跨域吗?跨域问题来源于JavaScript的同源策略,即只有协议主机名端口号(如...
-
Vue组件的自定义事件和全局事件总线怎么使用
-
vue中消息订阅与发布如何使用
vue中消息订阅与发布如何使用这篇文章主要介绍“vue中消息订阅与...
-
Vue显示图片的方式有哪些
-
vue引入静态jquery报错如何解决
vue引入静态jquery报错如何解决这篇文章主要介绍“vue引入...
-
vue-cropper怎么实现裁剪图片
-
怎么用Vue+NodeJS实现大文件上传
-
Vue如何实现简易跑马灯效果
-
Vue怎么指定不编译的文件夹和favicon.ico
Vue怎么指定不编译的文件夹和favicon.ico这篇文章主要介...
-
Vue中的插槽怎么使用