这篇文章发布于 2023年02月8日,星期三,23:48,归类于 JS实例。 阅读 20093 次, 今日 18 次 15 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10709 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。
一、问题描述
最近遇到了个bug,使用 div 模拟输入框,需要加上Enter回车键快捷提交,于是,我就写了类似下面的代码:
<div id="input" placeholder="中文输入法开启时候回车" contenteditable="plaintext-only"></div>
input.addEventListener('keydown', function (event) { if (event.code == 'Enter') { event.preventDefault(); console.log('表单提交触发了'); } });
结果发现,当打开中文输入法,希望回车确认英文的时候,会触发提交行为的执行。
如下实际渲染效果(iframe内嵌页面):
奇了怪了,我开发这么多年,之前似乎没遇到这个问题啊,怎么回事?
是浏览器升级了,是macOS系统原因,还是 div 输入框特殊行为?
后来整了个最原始的demo测试研究了下,找到了原因,原来是这么回事!
二、中文输入法与keyCode
以前,我处理键盘行为,都是用的 event.keyCode
,无他,就是兼容性好。
后来看 MDN 文档,说 keyCode 要废弃了,不推荐使用,如下图所示:
于是就研究了下,现在都推荐使用 event.key 或者 event.code 来判断按键内容。
为此,我还专门写了篇文章“告别JS keyCode”。
于是,这次的项目,我就使用了 event.code == 'Enter'
来判断用户是否按下了回车键。
本身逻辑上没有任何问题,但是实际操作却不是这么回事,只要用户输入框处于聚焦状态,此时,你只要按下回车键,就会触发相关的行为,哪怕中文输入法开启。
这就导致了回车冲突的产生,但是,使用 event.keyCode
却没有此问题,因为keyCode有个我过去曾误认为异常的特性,那就是中文输入法开启的时候,你按下任意的键,返回的 keyCode 值都是229。
以前以为是问题,现在才明白是特性。
解决之道
知道了原因,问题就好解决了,一是使用传统的keyCode属性判断好了,什么废弃不废弃的,不用考虑那么多,浏览器不会那么傻,真的不支持这个属性值的,那不知道有多少Web应用要哭爹喊娘了。
input.addEventListener('keydown', function (event) { if (event.keyCode == 13) { event.preventDefault(); console.log('表单提交触发了'); } });
此时,当中文输入法开启,输入内容再回车的时候,由于event.keyCode值是229,就不会执行表单提交,而是写入中文拼音,符合预期。
输入法关闭,此时回车的keyCode值是13,进入了预期的逻辑判断,执行表单提交行为,完美!
解决之道2
二是使用event.key代替event.code,如下所示:
input.addEventListener('keydown', function (event) { if (event.key == 'Enter') { event.preventDefault(); console.log('表单提交触发了'); } });
因为中文输入法开启的时候,任何常规按键的event.key返回值都是 ‘Process’,关闭的时候才会是 ‘Enter’,也可以避免中文输入法的回车冲突问题。
三、compositionstart解决方法
如果有人非要说,我就是喜欢KeyboardEvent.code,非他不嫁,我同时还希望输入法不会出来搞事情,有没有可能既要还要呢?
还是可以的,可以使用compositionstart和compositionend时间进行处理。
当中文输入法开启的时候,会触发compositionstart事件,关闭的时候会触发compositionend事件,因此,我们可以增加一个标志量,当输入法启动时候,不再触发对应的行为。
JS代码示意如下:
var flag = true; input.addEventListener('keydown', function (event) { if (flag && event.code == 'Enter') { event.preventDefault(); console.log('表单提交触发了'); } }); input.addEventListener('compositionstart', function (event) { flag = false; }); input.addEventListener('compositionend', function (event) { flag = true; });
眼见为实,下面的输入框就是修复后的iframe内嵌页效果,可以看到,当输入法开启,你再回车,是不会触发提交行为的:
更新
根据评论反馈,直接使用 event.isComposing 判断即可,无需这么麻烦~
三、如果是input输入框的解决方法
如果输入框不是div模拟的输入框,而是原生的 input 输入框,还有一种比较好的解决方法,那就是走原生form
表单提交,JS代码都不用写,浏览器自动识别回车,也没有各种乱七八糟的判断。
示意:
<form> <input required placeholder="中文输入法开启时候回车"> <button type="submit">提交</button> </form>
var form = document.querySelector('form'); var times = 0; form.addEventListener('submit', function (event) { event.preventDefault(); console.log('表单提交触发了' + (times ? ' +' + times: '~')); times++; });
实际演示效果:
四、结束说点什么
bug的出现还是归结于自己对键盘事件行为的理解还不够深入,这就是要在一线干活的好处,遇到问题,你才能对技能的掌握更加深入彻底。
所以,如果你想成为写一辈子代码的人。
不要花太多精力在管理上,你不去写代码,只了解一些表面的东西,是写不了一辈子代码的。
毕竟知识的更新迭代速度还是很快的。
好,就这些,日常工作学习的一点记录,希望可以帮到遇到类似问题的同学。
感谢阅读,欢迎分享!
😺😺😺
本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=10709
(本篇完)
- 告别JS keyCode (0.674)
- 网页制作辅助工具-jQuery标尺参考线插件 (0.241)
- HTML5终极备忘大全(图片版+文字版) (0.223)
- CSS :focus伪类JS focus事件提高网站键盘可访问性 (0.163)
- HTML inputmode与iOS Android软键盘类型测试 (0.132)
- js下拉菜单实现与可访问性问题的一些思考 (0.120)
- span与a元素的键盘聚焦性以及键盘点击性研究 (0.120)
- 翻译-盲人如何使用互联网的8个误区 (0.120)
- HTML enterkeyhint设置iOS/Android键盘enter键 (0.115)
- div模拟textarea文本域轻松实现高度自适应 (0.103)
- 密码强度效果最佳实现一定是HTML meter元素 (RANDOM - 0.060)
新bing聊天的输入框都有这个问题,输入法中按回车就直接提交了,体验很差。。。
mac自带的中文输入法,input输入框的keyup和keydown事件,输入拼音按enter,打印ev.keyCode是13,ev.code和ev.key都是’Enter’。
这个怎么办
其实不用这么麻烦,我们可以使用 isComposing 属性:https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/isComposing
溜啊~ 👍🏻
溜啊~ 👍🏻
溜啊~ 👍🏻
溜啊~ 👍🏻
挺有意思,我最近也用到这个属性,明明是挺简单的方案,但我体验下来有些ai聊天app都还有这个问题。
macos 下这个属性一直都是 false,没用
isComposing这个属性也不靠谱,我在处理搜狗浏览器,safari,火狐,chrome的时候发现他们有的没有这个属性,有的是compositionend和onchange时间的触发顺序也不一样,特别乱
f
旭哥 抱歉实在找不到联系方式 微博评论貌似也不能包含链接了 有个事想分享 safari tp 163终于把这个问题修了: https://github.com/WebKit/WebKit/commit/46c1b789ed0879837b4cd085fbd48e0ad702366d, iOS 11就开始的 调用uikit一个跟截图有关的方法后webview 所有 css transition就全失灵iOS Chrome iOS 微信都很容易复现: https://bugs.chromium.org/p/chromium/issues/detail?id=899130, https://bugs.chromium.org/p/chromium/issues/detail?id=1231712
我碰到类似的问题, 不过是监听 esc 键(产品需求), 是 contenteditable div + 内部 input 场景, 但是 esc 的按键一直监听不到, 按了之后都是取消 input 的聚焦
textarea 回车只想换行,但是触发了表单提交怎么办
textarea回车是不会触发表单提交的,默认无此行为。