By
被删
更新日期:
AngularJS(v1.5.8)已经成为项目们的基本框架,《玩转Angular1》系列用于记录项目中的一些好玩或者比较特别的思路。
本文简单介绍创建一个事件队列,来监听按键,并进行回调处理的过程。
基本思路
提供队列注册事件
通常,我们会需要在控制器中直接添加这样的按键监听事件,故这里我们通过服务的方式进行。
我们需要提供一个注册函数,来给控制器调用,需要传入:
- scope:作用域,用于提供执行环境
- callback:回调函数
因此,我们的注册服务的使用应该是这样的:
1 2
| EscKeyUp($scope, () => { callback(); });
|
我们可以提供一个缓存对象,里面通过随机产生的uuid来绑定{scope, callback}
数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| addCallback(callbacks, scope, callback) { const uuid = Math.random().toString(36).substr(2); if (typeof callback !== 'function') { console.log('callback is not a function.'); return; } this.CallbackObjscts[uuid] = { scope, callback }; callbacks.unshift(uuid); if (!this.isEventInit) { this.initEvent(); this.isEventInit = true; } }
|
可以看到,除了scope和callback,还需传入队列数组,该队列我们针对按键来分:
1 2 3 4
| EscCallbacks = [];
SpaceCallbacks = [];
|
注册监听事件
我们需要在文档添加事件监听:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| initEvent() { const that = this; document.addEventListener('keyup', ((e = (window as MyWindow).event as any) => { if (e && e.keyCode) { switch (e.keyCode) { case 27: that.executeCallback(that.EscCallbacks); break; case 32: that.executeCallback(that.SpaceCallbacks); break; } } }).bind(this), true); }
|
执行回调,并销毁注册
当按键事件触发时,我们需要:
1 2 3 4 5 6 7 8 9 10 11 12
| executeCallback(callbacks) { if (!callbacks.length) { return; } const uuid = callbacks.shift(); const {scope, callback} = this.CallbackObjscts[uuid] as any; scope.$apply(callback()); this.CallbackObjscts.splice(this.CallbackObjscts.findIndex(item => item === this.CallbackObjscts[uuid]), 1); }
|
KeyUp服务代码
KeyUp.ts
这里需要注意的是,方法中的this,默认指向KeyUp类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境,因为找不到内部的方法而导致报错。
一个比较简单的解决方法是,在构造方法中绑定this。
我们在app/shared/services
文件夹下添加KeyUp.ts
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| class KeyUpService { private CallbackObjscts: Object[] = []; private EscCallbacks: string[] = []; private SpaceCallbacks: string[] = []; private isEventInit: boolean = false;
constructor() { this.addEscCallback = this.addEscCallback.bind(this); this.addSpaceCallback = this.addSpaceCallback.bind(this); }
addEscCallback(scope, callback) { this.addCallback(this.EscCallbacks, scope, callback); }
addSpaceCallback(scope, callback) { this.addCallback(this.SpaceCallbacks, scope, callback); }
private addCallback(callbacks, scope, callback) { const uuid = Math.random().toString(36).substr(2); if (typeof callback !== 'function') { console.log('callback is not a function.'); return; } this.CallbackObjscts[uuid] = { scope, callback }; callbacks.unshift(uuid); if (!this.isEventInit) { this.initEvent(); this.isEventInit = true; } }
private executeCallback(callbacks) { if (!callbacks.length) { return; } const uuid = callbacks.shift(); const {scope, callback} = this.CallbackObjscts[uuid] as any; scope.$apply(callback()); this.CallbackObjscts.splice(this.CallbackObjscts.findIndex(item => item === this.CallbackObjscts[uuid]), 1); }
private initEvent() { const that = this; document.addEventListener('keyup', ((e = (window as MyWindow).event as any) => { if (e && e.keyCode) { switch (e.keyCode) { case 27: that.executeCallback(that.EscCallbacks); break; case 32: that.executeCallback(that.SpaceCallbacks); break; } } }).bind(this), true); } }
const KeyUp = new KeyUpService();
const {addEscCallback, addSpaceCallback} = KeyUp;
export { addEscCallback as EscKeyUp, addSpaceCallback as SpaceKeyUp };
export default KeyUp;
|
在控制器中使用
这里,我们为了方便,直接在登录页面进行监听:
1 2 3 4 5 6 7 8 9 10 11
| import { EscKeyUp, SpaceKeyUp } from '../../shared/services/KeyUp'; class KeyUp{ constructor(...){ ... for (let i = 1; i <= 3; i++) { EscKeyUp($scope, () => { Notify({ title: `Esc按下第${i}次注册` }) }); SpaceKeyUp($scope, () => { Notify({ title: `Space按下第${i}次注册` }) }); } } ... }
|
效果图:
可见,我们后注册的事件,会先执行。
结束语
这节主要简单介绍创建一个事件队列,来监听按键,并进行回调处理的KeyUp服务,并对外提供EscKeyUp()
和SpaceKeyUp()
方法。当然小伙伴们也可以拓展这些按键,又或者当队列为空的时候取消事件的监听等等。
此处查看项目代码
此处查看页面效果
查看Github有更多内容噢:https://github.com/godbasin
更欢迎来被删的前端游乐场边撸猫边学前端噢
如果你想要关注日常生活中的我,欢迎关注“牧羊的猪”公众号噢