动态获取input内容文本(排除候选拼音文本) - js事件
要想通过事件实时获取文本框文本,一开始是想到下面的方法,但实际效果都存在一定的缺点。
通过change/blur事件获取
- change事件只有在选中点击或者失焦的时候,才能够触发。
- blur事件则是只能在失焦才能除法。
我最初选择的是change事件,而这样显然是不符合实时获取的要求的。
然后在查找文档的时候,发现了input事件,这里的input指的是事件的名字。mdn对于input事件的解释是:
每当<input>元素的value值改变时,都会触发这个事件。
这个显然很适合我们的需求,先写个例子看一下效果。
<span>name:</span> <span id="txt"></span><br/> <label for="lastName"></label> <input id="lastName" type="text"><br/>
let txt = document.getElementById('txt'); let lastName = document.getElementById('lastName'); let num = 0; lastName.addEventListener('input', ()=>{ txt.innerText = lastName.value; console.log(num++); });
试了一下,效果的确很好,实时显示。
对于一般的普通文本框实时获取,input事件的确合适。但特殊情况下依然存在一些问题:
输入法的待选文本(拼音)也会同时获取显示,并且每一次输入都会触发事件。这会让显示的结果不够美观,同时,如果是需要实时获取并进行其它操作的话,比如模糊查询等,这会在输入时就产生很多次请求。(当然也可以使用防抖解决)
所以继续查找是否有更优的解决方案,于是发现了以下几种事件:
- compositionstart 事件触发于一段文字的输入之前
- compositionend 事件触发于当文本段落的组成完成或取消时
- compositionupdate 事件触发于字符被输入到一段文字的时候,在 compositionstart 事件之后不会立即执行
这些是MDN上找到的解释,很明显可以看出,这几个事件特别是前两个,是针对于有输入法候选词情况下产生的,很适合我们这种场景。有趣的是在MDN中,这几个事件被列在 Element 节点下,而不是事件节点下。
首先要实时获取文本框数据,在输入法状态输入完成后获取,使用 compositionend 事件。 但是在不使用输入法,或者删除输入的字符,是无法触发事件的,那么可以结合一下 input 事件使用。大致思路就是这样。示例:
let type = true; lastName.addEventListener('compositionstart', ()=> type = false); lastName.addEventListener('compositionend', ()=> type = true); lastName.addEventListener('input', ()=>{ window.setTimeout(()=>{ if(type) txt.innerText = lastName.value; }, 0); });
加定时器是为了保证 compositionend 事件执行后 type 状态改变成功,否则 input 事件触发时,type 可能仍为false。
测试效果:
效果差不多已经达到了。
兼容性:
input 事件只适合 ie9 以上版本,且只支持文本和密码输入框。
composition~ 事件 MDN 上是支持 ie 的,但并未写清版本。
案例代码 es5 语法时最低支持 ie9。
参考: