saber酱的抱枕

Fly me to the moon

12/28
10:14
学习

JavaScript的复合事件(composition event)

今天看《JavaScript高级程序设计》时看到了DOM3级事件中的复合事件(composition event),可以用来接收IME输入的内容,我便研究了一番。

复合事件(composition event)有3个事件:

compositionstart:在IME的文本复合系统打开时触发,表示要开始输入了。
compositionupdate:在向输入字段中插入新字符时触发。
compositionend:在IME的文本复合系统关闭时触发,表示返回正常键盘的输入状态。

浏览器能力检测:

document.implementation.hasFeature("CompostionEvent");

兼容性:
IE11、Edge、Chrome、Firefox 都已经支持。

IME(Input Method Editor)通俗点说就是输入法(如搜狗输入法)。有时候我们是没有使用IME的,比如直接输入英文字母、数字等情况,内容是直接输入的。但是使用输入法的时候,有个“上屏”步骤,也就是选字。

举个例子,我输入“雪见”(xuejian)这个词:

composition event javascript 复合事件

在我选择“雪见”两个字之前,JavaScript能不能获取到我现在输入的内容(xuejian)呢?这就有个关键的地方,就是上屏之前,输入框里有没有出现我们输入的英文。如果出现了英文,那么用oninput和compositionupdate都可以获取我们输入的内容;如果输入框里没有出现英文,那么oninput和compositionupdate都获取不到。(chrome里始终都会出现英文,Firefox某些情况下不会出现。所以谷歌大法好)

所以,compositionupdate可以被oninput完全替代,而且返回值也完全一致。那么复合事件(composition event)还有什么卵用呢?其实它的另外两个方法:compositionstart和compositionend还是独特的,不能被其他事件替代。但是这两个事件的作用也很小,我是想不出什么好的应用场景。

虽然这么说,但是这个玩意我还是花了点时间来试验的,还是记录一下吧。


把复合事件(composition event)的3个事件全部添加上来做试验(网址使用命运冠位指定贴吧,在搜索框做实验)。

代码如下:

var a=document.querySelector("#wd1");

a.addEventListener("compositionstart",function(e){
    console.log("start:"+e.data);
});

a.addEventListener("compositionupdate",function(e){
    console.log("update:"+e.data);
});

a.addEventListener("compositionend",function(e){
    console.log("end:"+e.data);
});

我使用输入法输入“xuejian”并选词:

composition event javascript 复合事件

输出结果:

composition event javascript 复合事件

1. compositionstart

开始对输入法输入时会触发这个事件。比如我开始输入第一个字母“x”的时候,就会触发compositionstart事件。那么它的返回值“命运冠位指定”是什么呢,就是本次用IME输入时被替换掉的文字:

composition event javascript 复合事件

贴吧这个输入框,当我们点击的时候,会自动选中里面现有的文字。当我们自己再输入字符的时候,这些被选中的文字就没了,被我们输入的字符取代了。compositionstart的返回值就是这些被替代的文字。如果输入之前,没有选择其他文字,那么就不会有文字被替代,compositionstart的返回值就是空的。

注意:复合事件(composition event)的所有事件都只会在我们用IME输入文字时触发。比如这个输入框绑定了复合事件,我们一会儿不用输入法直接输入,一会儿又使用输入法来输入。但只有在用输入法(IME)输入的时候才会触发复合事件(composition event)。下同。

2.compositionupdate

当我们在输入法里输入的时候,每一次输入以及最后的上屏(选字)都会触发compositionupdate事件,它的返回值是我们这次输入的所有字符。

之前我说过了,这个事件可以被oninput替代,连返回值都一模一样。但是因为compositionupdate是和IME联系的,所以有些地方比较特别:

有些按键,IME可以接受,但不显示出来,这时候也依然会触发compositionupdate事件。比如搜狗输入法可以输入分号等字符进入一些特殊模式,我输入“xuejian;”进入特殊模式,但是分号“;”并没有出现在搜狗输入法的显示框和浏览器的输入框里,依然会触发compositionupdate事件。又或者在选词的时候按Page Up、Page Down 翻页,输入法对这些按键有反应,那么就会触发compositionupdate事件。

但有些按键IME不接受,比如用搜狗输入法的时候按数字锁定键,搜狗输入法对此不理会,那么就不会触发compositionupdate事件。

3.compositionend

当我们完成上屏(选字)之后,本次输入过程结束,compositionend会返回这次输入的最终内容。

注意只是返回本次输入的结果,如果进行了多次输入,也只会返回最后一次的结果,不会把所有结果连起来。


本次研究就到这里,结论就是复合事件(composition event)没什么卵用。

一开始我还想着,在搜索框根据输入的文字进行联想,这种情况下复合事件(composition event)有没有用呢?

composition event javascript 复合事件

结果实践后就发现不应该使用复合事件(composition event),因为不使用IME输入的时候它就不会被触发,如果用户直接输入英文和数字那就歇菜了。oninput完爆之。

而且复合事件也获取不到候选词,在我手动选词之前,JavaScript依然只能获取到英文,没什么优势。

JavaScript的复合事件(composition event)