加上快捷键,让你的网站酷起来( 二 )


在某个按键按下时,需要考察当前按键和已经按下的其他按键,看看会构成哪些按键组合(拼接按键组合字符串,作为激活事件的依据):
在事件中只需要专门捕获按键组合,而不用考虑这个按键或者按键组合是否已经定义了执行某个方法 。然后把捕获的组合传入另一个方法,由他来查找这个按键组合是否定义,以及执行已定义的回调 。举个例子:
假如先按下a,没有其他按键在这之前被按下,按键组合就是a,同时a存入,执行传入a;
继续按下m,构成按键组合a+m,m存入,执行传入a+m;
然后当y被按下时,当前按键跟已经按下的其他按键构成的组合包括a+y和m+y,如果按照严格一点的检测方式,只跟当前按键最近的一次按键匹配,就是m+y,如果你需要定义三个按键的组合快捷键,那当前的按键组合是a+m+y 。(不过通常来说,两个按键的组合就已经够用了);
然后仍然要把当前键码存入中;但是有一个特例:那就是修饰键 。修饰键最好定义成与非修饰键的组合构成快捷键,在按住一个非修饰键时,我们可以通过查询事件对象来判断某个修饰键是否按下,而不需要通过前述的;因此按下修饰键并不需要保存到里;在网站中,采用了严格的检测方式,执行传入m+y
当keyup时,事情就简单多了,把相应的键码从中删除即可 。

触发组合事件
接下来就是在方法中,处理接收到的用户当前的按键组合,查询这个组合是否定义了回调,有就激活,没有则忽略 。问题是如果这个按键组合已经定义了事件,那如何激活它呢?
要确定激活方式,就得确定事件的注册方式;我们需要实现一个事件注册方法,接受一个快捷键组合,以及相应回调;
有一种很直观的思路是这样的:注册这个组合对应的字符串为一个自定义事件,比如m+y,传入的回调就是这个事件的回调,即:

然后在用户按下m以及y之后,传入这个组合,直接这个事件,自然就会执行相应方法 。如果是一个从未定义过回调的方法,同样,只不过它没有绑定事件所以什么都不做 。
但是这样会有严重的性能问题:
注册一个快捷键就得注册一个自定义事件,j是一个,k是一个,m+y是一个……这样你注册的事件会越来越多,对性能是一个比较严重的损耗;
假如你想停止使用快捷键功能,要么逐个解绑所有的快捷键事件 。要么从源头上解绑 keyup,相关事件 。都是非常麻烦的 。
统一的自定义事件
解决方法仍然是用自定义事件,不过全局我们只注册一个自定义事件,我们维持一个键值对(对象),键就是我们注册的快捷键组合,值就是当这个快捷键被触发时执行的方法 。注册新的快捷键组合时,往这个对象中添加新的键值对即可 。
当用户按键时,同样是将用户的按键组合传入方法,,然后我们检测用户按下的按键组合作为属性是否存在于前述对象中,如果存在则触发一个统一的事件,并传入这个组合键,让这个统一的事件去分发不同快捷键对应的方法进行执行 。

这样做很明显的好处是
注册新的事件时只需要操作对象即可,不再需要再操作事件相关的逻辑,不再添加新的自定义事件 。
可以随时解绑快捷键功能,只需要停止触发自定义的:事件就可以了;
事件触发区域
另外还有一个需要格外注意的点是:我们监听键盘事件是绑定在整个文档对象上的,但是由于浏览器的事件传播机制,如果用户在与表单交互,比如input,,用户的文字输入行为最终会冒泡到上,插件如果不分情况的进行监听则很不合理的;我们需要明确区分用户确实是要在页面中输入内容和用户想触发快捷键这两种行为,因此在事件中需要检测事件的,如果是一个表单交互对象就不要触发任何事件 。