键盘事件与文本框变化的过程
键盘事件最基本的应用场合是控制文本框元素,而我们要讨论的,就是几个键盘事件:keydown
、keypress
、keyup
、textInput
发生的时机与文本输入的过程的关系。先看一段代码:
<input type="text" id="input"></input>
<script>
var input = document.getElementById('input');
input.addEventListener('keydown', function() {
console.log('keydown');
}, false);
input.addEventListener('keypress', function() {
console.log('keypress');
}, false);
input.addEventListener('keyup', function() {
console.log('keyup');
}, false);
input.addEventListener('textInput', function() {
console.log('textInput');
}, false);
</script>
查看控制台可以看到键盘事件的执行顺序,这里事件的执行分为两种情况,一种是按下字符键,chrome下执行的顺序为keydown
->keypress
->textInput
->keyup
,如果按照不放就交替执行keydown
和keypress
;另一种是按下非字符键,chrome下执行顺序为keydown
->keyup
,如果按着不放就不停地执行keydown
。
事件的顺序搞清楚了,但我们还要看清键盘事件发生与文本框变化的顺序。把上面代码中的每个事件处理程序再加一句console.log(input.value)
,按一个字符。可以看到,除了keyup
外,keydown
、keypress
、textInput
事件并不会输出刚按下的字符,说明他们在文本框变化之前发生而keyup
在之后发生。进一步地,也可以给每个事件加个alert()
看看,虽然由于alert()
的干扰导致keyup
不发生(单步调试得出的结论),但这样一步步执行也能直观看出上面的结论。
理清这些关系有什么用呢?当然是为了起前端工程的一大目标:做出更好地交互。比如你要做个有关键词提示的搜索框,由于只有keyup
事件是在文本框变化后触发的,也就意味着弹出提示的代码只有挂在keyup
事件上才能在输入字符后获取到输入框最新的value,而挂在其他事件上就会出现提示与输入慢半拍的诡异现象。
最后要注意,虽然各浏览器基本遵循上面的事件执行顺序,但不同浏览器对键盘事件的实现仍有差别,比如火狐和IE并不支持textInput
事件;而同时对于非字符键,也不一定就按上面提到的只响应keydown
和keyup
,比如在火狐下按backspace键也具有字符键的行为。
对用户输入字符进行正则转义
数据交互的可靠与安全是前端工程需要考虑的重要一环,我们的用户既可能输入一段有歧义的字符,也随时可能给你来段sql注入或xss,这里我也遇到一个简单点的情景:如何拿用户输入的内容来构建有效的正则进行查询。
考虑到用户可能会输入一些正则的专用符号,如果不对这些符号进行转义就直接把整个字符串拿去构造正则,那势必会使查询结果背离我们的本意。正则表达式里对特殊符号转义只要在前面加\
,所以思路就是将源字符串中的特殊符号替换为\待转义字符
。实现如下:
function transfer(string) {
return string.replace(/[\.\/\\\^\$\*\+\?\[\]\(\)]/g, '\\$&');
}
用到了字符串的replace
方法,第一个参数一个是全局匹配所有待转义字符的正则;第二个参数是个$表达式,$&
获取所有与正则相匹配的子串,注意这里要在其前面加上\\
而非\
,因为在普通字符串里使用\
也得写为\\
进行转义。
可能有人会问,$&
不是相当于RegExp.lastmatch
匹配最近一次匹配项吗,为何使用它获取全局正则的所有匹配项?
可以这么想,replace
对全局正则匹配项的替换是逐个进行的,每匹配一个子串就用第二个参数的规则替换一次。所以用$&
每次替换最近一次匹配项,也就能到达看起来一次替换了全局正则的所有匹配项效果。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。