做实时的表单表单校验时,如果输入的是非拉丁语言,那你可能会遇到下面的问题:
如上图所示,文本框不允许输入 '
之类的特殊字符,当用户在敲击拼音、还未最终输入时就已经触发了校验,提示输入不合法,有点尴尬。通常我们都是监听 input
或者 change
事件来校验用户输入,也就是说在用户输入拼音的过程中就已经触发了相关事件,进而触发校验。
现实中遇到类似问题时,我们一般会认为是输入法处理不当,这种底层的问题不应该由前端来填坑,然后就放弃治疗了。
那到底有没有前端规避这一问题的方法呢?还真有:DOM 提供了 Composition 事件 API。不过,应该很少有人关注到这几个事件,或者是笔者太孤陋寡闻,不然不会最近才留意到。
根据规范,Composition 事件触发顺序如下:
- 输入开始时触发
compositionstart
- 选择字/词完成输入时触发
compositionend
- 输入过程中每次击键时触发
compositionupdate
,包括 start 事件以后立即触发,end 事件以前立即触发 - Composition 事件以后触发
input
事件
通过 Composition 事件,在 compositionend
里校验非直接输入,就能有效地避免不恰当的校验时机产生的用户体验问题。
<h2>切换至中文或者其他非拉丁语系输入法</h2> <p> <label for="title1">监听 Input 校验</label> <input type="text" id="title1"> </p> <p> <label for="title2">中文输入法时监听 Composition 事件校验</label> <input type="text" id="title2"> </p>
.error { border: 3px solid red; }
const title1 = document.getElementById('title1'); const rule = /^[1-9a-zA-Z\u4e00-\u9fa5]+$/; const errorClassname = 'error'; function validate(node) { const value = node.value; if (!rule.test(value)) { node.classList.add(errorClassname); } else { node.classList.remove(errorClassname); } console.log(`Input -> ${value}`); } title1.addEventListener('input', function(event) { validate(this); }); let compositio = false; title2.addEventListener('compositionstart', function() { compositio = true; }); // 非拉丁语言输入校验 title2.addEventListener('compositionend', function(event) { validate(this); }); // 普通输入校验 title2.addEventListener('input', function(event) { if (!compositio) { validate(this); } })
原文链接:https://csspod.com/dom-composition-event/
参考链接:
https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event
https://blog.evanyou.me/2014/01/03/composition-event/