惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
博客园 - 司徒正美
A
About on SuperTechFans
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
爱范儿
爱范儿
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
Google DeepMind News
Google DeepMind News
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
F
Fortinet All Blogs
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
D
Docker
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
Jina AI
Jina AI
H
Help Net Security
量子位
IT之家
IT之家

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
奇了怪了,输入法和JS Enter回车提交冲突 « 张鑫旭-鑫空间-...
张鑫旭,zhangxinxu · 2023-02-08 · via 张鑫旭-鑫空间-鑫生活

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 要废弃了,不推荐使用,如下图所示:

keyCode废弃

于是就研究了下,现在都推荐使用 event.key 或者 event.code 来判断按键内容。

为此,我还专门写了篇文章“告别JS keyCode”。

于是,这次的项目,我就使用了 event.code == 'Enter' 来判断用户是否按下了回车键。

本身逻辑上没有任何问题,但是实际操作却不是这么回事,只要用户输入框处于聚焦状态,此时,你只要按下回车键,就会触发相关的行为,哪怕中文输入法开启。

这就导致了回车冲突的产生,但是,使用 event.keyCode 却没有此问题,因为keyCode有个我过去曾误认为异常的特性,那就是中文输入法开启的时候,你按下任意的键,返回的 keyCode 值都是229。

中文输入法均返回keyCode 229

以前以为是问题,现在才明白是特性。

not a bug feature

解决之道

知道了原因,问题就好解决了,一是使用传统的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

(本篇完)