javascript事件机制学习(一)——个人实现
2017-03-27 14:59
465 查看
起因:在面试的时候被问到在不提供任何DOM API,不能使用jQuery,如何实现事件的监听和触发。
需求:需要在全局范围监听事件。为了方便事件类型的扩展,提供注册事件,移除事件的方法。对于某一类的时间,提供监听事件,触发事件,和移除事件三种方法。因此针对需求,设计以下的数据结构:
结构:用一个Object存储全部的事件,其中包括三个(或多个)handler,为addHandler,removeHandler和setupHandler。分别用于在第一次注册注册事件的时候,监听该类型的事件时,以及移除对改事件的监听时执行回调。EventQueue用于存储,监听该时间的全部事件对象。on用于将事件对象添加到响应的队列里面,off用于将事件对象从监听队列里移除,fire用于触发这一类事件。依次执行队列里面的时间。
代码分析:
整体数据结构:
注册事件:
注册事件分为两种情况,一种是该事件已被注册的情况。这种情况,把提供的eventObj的时间队列添加到原有的队列后面。如果还没有注册该事件,则根据eventObj中提供的handler,创建新的监听对象。
移除事件类型:
先检查存不存在该类型的事件,存在的话,则从eventMap中delete掉。
监听事件:
首先需要确保监听类型,对象和回调都提供。并且要判断监听的事件类型是否存在。如果不满足条件,直接返回。
然后需要判断,该elem是否已经监听过这个事件了。如果有,则把callback放到原来的回调队列里面。如果还没有监听的话,那么产生一个{},其中包括id,执行的对象elem和回调队列。将该obj放到监听事件的队列里面。
触发事件:
移除事件:
找到该元素在该类型中的事件对象,然后从queue中移除。并且执行removeHandler
完整代码:
https://github.com/lizzyDeng/personalLib/blob/master/EventManager.js
需求:需要在全局范围监听事件。为了方便事件类型的扩展,提供注册事件,移除事件的方法。对于某一类的时间,提供监听事件,触发事件,和移除事件三种方法。因此针对需求,设计以下的数据结构:
结构:用一个Object存储全部的事件,其中包括三个(或多个)handler,为addHandler,removeHandler和setupHandler。分别用于在第一次注册注册事件的时候,监听该类型的事件时,以及移除对改事件的监听时执行回调。EventQueue用于存储,监听该时间的全部事件对象。on用于将事件对象添加到响应的队列里面,off用于将事件对象从监听队列里移除,fire用于触发这一类事件。依次执行队列里面的时间。
代码分析:
整体数据结构:
var EventManager = function(){ this.eventMap = {}; this.handlers = ["add","remove","setup"]; this.guid = 0; };
注册事件:
EventManager.prototype.registerEvent = function(name,eventObj) { var eventMap = this.eventMap; if(!eventMap.hasOwnProperty(name)){ eventMap[name] = {}; for(var i=0,len=this.handlers.length; i<len; i++){ var handlerName = this.handlers[i] + "Handler"; eventMap[name][handlerName] = eventObj[handlerName] || null; } eventMap[name]["queue"] = []; }else{ for(var key in eventObj){ if( !key.test(/'queue'/g)){ eventMap[name][key] = eventObj[key]; }else{ eventMap[name][key].concat(eventObj[key].slice(0)); } } } };
注册事件分为两种情况,一种是该事件已被注册的情况。这种情况,把提供的eventObj的时间队列添加到原有的队列后面。如果还没有注册该事件,则根据eventObj中提供的handler,创建新的监听对象。
移除事件类型:
EventManager.prototype.removeEvent = function(name){ var eventMap = this.eventMap; if(!eventMap.hasOwnProperty(name)){console.log("has no such event type"); return ;} delete eventMap[name]; }
先检查存不存在该类型的事件,存在的话,则从eventMap中delete掉。
监听事件:
EventManager.prototype.on = function(elem,type,callback){ var args = Array.prototype.slice.call(arguments, 0); if(args.length < 3 || !this.eventMap.hasOwnProperty(type)) return ; // 如果参数提供的不齐全,或者没有该type,那么直接返回 //这里应该调整一下参数,先不实现 var queue = this.eventMap[type]["queue"], addHandler = this.eventMap[type]["addHandler"], setupHandler = this.eventMap[type]["setupHandler"], i = 0, len = queue.length,dom = "dom"; for(; i<len; i++){ if(elem.nodeType == 1 && queue[i][dom] === elem){//该元素已经监听过的情况 addHandler &&addHandler.apply(elem); queue[i]["callbacks"].push(callback); break; } } if(i == len){ // 该元素还没有监听任何事件 var temp = { "id" : this.guid++, "dom" : elem, "callbacks" : [] }; setupHandler && setupHandler.apply(elem); temp["callbacks"].push(callback); queue.push(deepClone(temp)); temp = null; } }
首先需要确保监听类型,对象和回调都提供。并且要判断监听的事件类型是否存在。如果不满足条件,直接返回。
然后需要判断,该elem是否已经监听过这个事件了。如果有,则把callback放到原来的回调队列里面。如果还没有监听的话,那么产生一个{},其中包括id,执行的对象elem和回调队列。将该obj放到监听事件的队列里面。
触发事件:
EventManager.prototype.fire = function(elem,type){ var queue = this.eventMap[type]["queue"]; if(arguments.length < 2 || queue === undefined) return; var i=0,len = queue.length; for(; i<len; i++){ var context = queue[i]["dom"], callbacks = queue[i]["callbacks"]; callbacks.forEach(function(callback){ callback.call(context,elem); }); } }首先也要确保传参正确,并且存在该事件类型。如果没有,则直接返回。 然后依次取出queue里面的监听对象。获取执行回调的context和回调们。依次执行
移除事件:
EventManager.prototype.off = function(elem,type){ var queue = this.eventMap[type]["queue"]; if(arguments.length < 2 || queue == undefined) return ; var i=0, len= queue.length,removeHandler = this.eventMap[type]["removeHandler"]; for(; i<len; i++){ if(elem.nodeType == 1 && queue[i]["dom"] === elem){ removeHandler && removeHandler.apply(elem); queue.splice(i,1); break; } } }
找到该元素在该类型中的事件对象,然后从queue中移除。并且执行removeHandler
完整代码:
https://github.com/lizzyDeng/personalLib/blob/master/EventManager.js
相关文章推荐
- Flex事件机制学习-SWF间共享事件实现通信
- Flex事件机制学习-自定义事件实现类间通信 .
- 【探讨】javascript事件机制底层实现原理
- 利用Javascript实现一套自定义事件机制
- javascript事件机制底层实现原理
- JavaScript学习笔记之事件处理机制
- 韩顺平 javascript教学视频_学习笔记22_js事件驱动机制_js事件分类_js访问css技术
- Effective C# 学习笔记(二十五)以事件机制来实现通知
- 韩顺平 javascript教学视频_学习笔记23_js事件驱动机制深入理解_js常用事件_js版计算器
- CocosCreator项目学习系列<二>关于Button(添加事件)输入控制交互条件的触发_实现虚拟按钮控制_JavaScript
- 使用javascript和java模仿实现事件回调机制
- 【JavaScript 学习--12】JS深入理解调用栈,事件循环机制,回调队列
- java基础学习总结——关于Java中事件分发和监听机制实现的代码实例
- 【iScroll源码学习03】iScroll事件机制与滚动条的实现
- android个人学习笔记-触摸事件机制
- 【iScroll源码学习03】iScroll事件机制与滚动条的实现
- 事件处理程序实现的另一种方法:浏览器的事件监听机制实现“1事件对应n事件处理程序”(Javascript)
- Flex事件机制学习-自定义事件实现类间通信
- Lua中实现类似C#的事件机制
- DataGrid中绑定javascript事件,实现删除提示和变换背景色