详解javascript实现自定义事件

我们平时在操作dom时候经常会用到onclick,onmouSEOver等一系列浏览器特定行为的事件, 那么自定义事件,顾名思义,就是自己定义事件类型,自己定义事件处理函数,在合适的时候需要哪个事件类型,就去调用哪个处理程序

1.js所支持的浏览器默认事件

浏览器特定行为的事件,或者叫系统事件,js默认事件等等都行,大家知道我指的什么就行,下文我叫他js默认事件。 js默认事件的事件绑定,事件移出等一系列操作,相信大家都有用到过,如:

又或者

//非ie
oDiv.addEventListener("click",function(){
alert("你点击了我");
},false);

//ie
oDiv.attachEvent("onclick",function(){
alert("你点击了我");
});

所有我就不做过多的研究,毕竟我们来讨论js自定义事件,这里给出一个我之前封装过的处理js默认事件的代码

调用时候直接用domEvent.addEvent(,);直接调用 //使用时候,先用addEvent添加事件,然后在handleFun里面直接写其他函数方法,如getEvent; //addEventListener和attachEvent---都是dom2级事件处理程序 var domEvent = { //element:dom对象,event:待处理的事件,handleFun:处理函数 //事件名称,不含“on”,比如“click”、“mouSEOver”、“keydown”等 addEvent:function(element,event,handleFun){ //addEventListener----应用于mozilla if(element.addEventListener){ element.addEventListener(event,handleFun,false); }//attachEvent----应用于IE else if(element.attachEvent){ element.attachEvent("on"+event,handleFun); }//其他的选择dom0级事件处理程序 else{ //element.onclick===element["on"+event]; element["on"+event] = handleFun; } },//事件名称,含“on”,比如“onclick”、“onmouSEOver”、“onkeydown”等 removeEvent:function(element,handleFun){ //removeEventListener----应用于mozilla if (element.removeEventListener) { element.removeEventListener(event,false); }//detachEvent----应用于IE else if (element.detachEvent) { element.detachEvent("on"+event,handleFun); }//其他的选择dom0级事件处理程序 else { element["on"+event] = null; } },//阻止事件冒泡 stopPropagation:function(event){ if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true;//IE阻止事件冒泡,true代表阻止 } },//阻止事件默认行为 preventDefault:function(event){ if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false;//IE阻止事件冒泡,false代表阻止 } },//获得事件元素 //event.target--非IE //event.srcElement--IE getElement:function(event){ return event.target || event.srcElement; },//获得事件 getEvent:function(event){ return event? event : window.event; },//获得事件类型 getType:function(event){ return event.type; } };

接下类我们不如正题,js自定义事件

2.对象直接量封装js自定义事件

根据上面的封装,我们可以这样构思

添加事件 },fireEvent: function(){ //触发事件 },removeEvent: function(){ //移除事件 } };

相信这样大家还是比较好理解的,然后又有一个问题大家可以想到,那就是,js默认事件,js可以一一对应,知道那个是那个,那么我们的自定义事件呢,这个一一对应的映射表只能我们自己去建立,然后我这样

代码 },fireEvent: function(){ //触发代码 },removeEvent: function(){ //移出代码 } };

我是这样构建这个映射关系的

这样每一个类型可以有多个处理函数,以便于我们以后扩充 接下来就是代码方面的实战的,编写具体的处理代码了…

相信大家对于这个思路已经很清楚了,我直接附上代码

自定义事件类型, handler -> 自定义事件回调函数 addEvent: function(type,handler){ //判断事件处理数组是否有该类型事件 if(eventTarget.handlers[type] == undefined){ eventTarget.handlers[type] = []; } //将处理事件push到事件处理数组里面 eventTarget.handlers[type].push(handler); },//触发一个事件 //event -> 为一个js对象,属性中至少包含type属性, //因为类型是必须的,其次可以传一些处理函数需要的其他变量参数。(这也是为什么要传js对象的原因) fireEvent: function(event){ //判断是否存在该事件类型 if(eventTarget.handlers[event.type] instanceof Array){ var _handler = eventTarget.handlers[event.type]; //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件 for(var i = 0; i < _handler.length; i++){ //执行触发 _handler[i](event); } } },//注销事件 //type -> 自定义事件类型, handler -> 自定义事件回调函数 removeEvent: function(type,handler){ if(eventTarget.handlers[type] instanceof Array){ var _handler = eventTarget.handlers[type]; //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件 for(var i = 0; i < _handler.length; i++){ //找出本次需要处理的事件下标 if(_handler[i] == handler){ break; } } //删除处理事件 _handler.splice(i,1); } } };

这是一种调用运行的方法

这种方法有一个缺点,不能删除该处理事件,因为我们是用映射表做的,而且也不提倡,直接给映射表里面存这么多数据,有点多。

另一种方法,将处理事件提取出来(推荐)

也可以这样,传递更多的参数

总结:字面量这种方法,有点儿缺点,就是万一一不小心,把某个属性在handler函数里面,赋值null,这样会造成我们的的eventTarget 方法崩盘。看来原型应该是个好方法,更安全一点。

3.对象原型封装js自定义事件

由于前面思路基本都讲清楚了,这里我直接附上代码,大家可以研究下其中的利弊,或许你可以找到更好的方法解决Ta…

为一个js对象,属性中至少包含type属性, //因为类型是必须的,其次可以传一些处理函数需要的其他变量参数。(这也是为什么要传js对象的原因) fireEvent: function(event){ //模拟真实事件的event if(!event.target){ event.target = this; } //判断是否存在该事件类型 if(this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; //在同一个事件类型下的可能存在多种处理事件,找出本次需要处理的事件 for(var i = 0; i < handlers.length; i++){ //执行触发 handlers[i](event); } } },handler){ //判断是否存在该事件类型 if(this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; //在同一个事件类型下的可能存在多种处理事件 for(var i = 0; i < handlers.length; i++){ //找出本次需要处理的事件下标 if(handlers[i] == handler){ break; } } //从事件处理数组里面删除 handlers.splice(i,1); } } };

调用方法

var target = new EventTarget();
target.addEvent("eat",b);

target.fireEvent({
type: "eat"
}); //123

原型这种方法,与直接量方法功能是一样的…

以上就是本文的全部内容,希望对大家的学习有所帮助。

相关文章

事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数...
js小数运算会出现精度问题 js number类型 JS 数字类型只有number类型,number类型相当于其他强类型语言...
什么是跨域 跨域 : 广义的跨域包含一下内容 : 1.资源跳转(链接跳转,重定向跳转,表单提交) 2.资源...
@ &quot;TOC&quot; 常见对base64的认知(不完全正确) 首先对base64常见的认知,也是须知的必须有...
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : 的缩写,说都能直接说出来 :模型, :视图, :视图模...
首先我们需要一个html代码的框架如下: 我们的目的是实现ul中的内容进行横向的一点一点滚动。ul中的内容...