这篇文章主要为大家介绍了javascript实现自定义事件的方法,自定义事件,顾名思义,就是自己定义事件类型,自己定义事件处理函数,javascript如何实现自定义事件,需要了解的朋友可以参考下

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

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

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

//DOM0级事件处理程序
var oDiv = document.getElementById('oDiv');
oDiv.onclick = function(){
alert("你点击了我");
}

又或者

//DOM2级事件处理程序
var oDiv = document.getElementById('oDiv'); //非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,event,handleFun){
//removeEventListener----应用于mozilla
if (element.removeEventListener) {
element.removeEventListener(event,handleFun,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自定义事件

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

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

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

var eventTarget = {
//保存映射
handlers:{},
addEvent: function(){
//处理代码
},
fireEvent: function(){
//触发代码
},
removeEvent: function(){
//移出代码
}
};

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

handlers = {
"type1":[
"fun1",
"fun2",
// "..."
],
"type2":[
"fun1",
"fun2"
// "..."
]
//"..."
}

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

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

//直接量处理js自定义事件
var eventTarget = {
//保存事件类型,处理函数数组映射
handlers:{},
//注册给定类型的事件处理程序,
//type -> 自定义事件类型, 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);
}
}
};

这是一种调用运行的方法

eventTarget.addEvent("eat",function(){
console.log(123); //
});
eventTarget.fireEvent({type: "eat"});

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

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

function b(){
console.log(123);
}
eventTarget.addEvent("eat",b);
eventTarget.fireEvent({
type: "eat"
}); //
eventTarget.removeEvent("eat",b);
eventTarget.fireEvent({type: "eat"}); //空

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

eventTarget.fireEvent({
type: "eat",
food: "banana"
});
function b(data){
console.log(data.food); //banana
}

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

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

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

//自定义事件构造函数
function EventTarget(){
//事件处理程序数组集合
this.handlers = {};
}
//自定义事件的原型对象
EventTarget.prototype = {
//设置原型构造函数链
constructor: EventTarget,
//注册给定类型的事件处理程序,
//type -> 自定义事件类型, handler -> 自定义事件回调函数
addEvent: function(type, handler){
//判断事件处理数组是否有该类型事件
if(typeof this.handlers[type] == 'undefined'){
this.handlers[type] = [];
}
//将处理事件push到事件处理数组里面
this.handlers[type].push(handler);
},
//触发一个事件
//event -> 为一个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);
}
}
},
//注销事件
//type -> 自定义事件类型, handler -> 自定义事件回调函数
removeEvent: function(type, 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);
}
}
};

调用方法

function b(){
console.log(123);
} var target = new EventTarget();
target.addEvent("eat", b); target.fireEvent({
type: "eat"
}); //

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

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

详解javascript实现自定义事件的更多相关文章

  1. 详解Vue 方法与事件处理器

      本篇文章主要介绍了详解Vue 方法与事件处理器 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 方法与事件处理器 方法处理器 可以用 v-on 指令监听 DOM 事件 ...

  2. 详解Javascript的继承实现(二)

    上文<详解Javascript的继承实现>介绍了一个通用的继承库,基于该库,可以快速构建带继承关系和静态成员的javascript类,好使用也好理解,额外的好处是,如果所有类都用这种库来构 ...

  3. jQuery:详解jQuery中的事件(二)

    上一篇讲到jQuery中的事件,深入学习了加载DOM和事件绑定的相关知识,这篇主要深入讨论jQuery事件中的合成事件.事件冒泡和事件移除等内容. 接上篇jQuery:详解jQuery中的事件(一) ...

  4. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  5. 详解 javascript中offsetleft属性的用法(转)

    详解 javascript中offsetleft属性的用法 转载  2015-11-11   投稿:mrr    我要评论 本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一 ...

  6. 详解javascript中的this对象

    详解javascript中的this对象 前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript可以通过一定的 ...

  7. 详解JavaScript的任务、微任务、队列以及代码执行顺序

    摘要: 理解JS的执行顺序. 作者:前端小智 原文:详解JavaScript的任务.微任务.队列以及代码执行顺序 思考下面 JavaScript 代码: console.log("scrip ...

  8. 详解javascript的类

    前言 生活有度,人生添寿. 原文地址:详解javascript的类 博主博客地址:Damonare的个人博客 Javascript从当初的一个"弹窗语言",一步步发展成为现在前后端 ...

  9. 【转】详解JavaScript中的this

    ref:http://blog.jobbole.com/39305/ 来源:foocoder 详解JavaScript中的this JavaScript中的this总是让人迷惑,应该是js众所周知的坑 ...

随机推荐

  1. bootstrap中如何使input中的小图标获得点击事件

    bootstrap中,放入input中的小图标是不能点击的. 在表单中经常遇见密码旁边的眼睛图标点击后,可使密码可见. 要使小图标获得点击事件,可在小图标上覆盖一个跟小图标一样大的透明层,然后给透明层 ...

  2. 对于jsp中编码的理解

    1.会话都是从客户端也就是浏览器开始发起的,首先用户将地址输入到地址栏中, 当用户输入enter或者点击转到的按钮时,浏览器会根据当前页面的charset对地址栏中的地址进行encode一次,当服务器 ...

  3. 【RF库Collections测试】combine lists

    Arguments: [ *lists ]Combines the given `lists` together and returns the result. The given lists are ...

  4. Java取出字符串中的大写字母,并倒序输出

    package catic.test; /** * @ClassName: TestXBQ * @Description: TODO 输出字符串中的大写字母,并倒序输出 * @author xbq * ...

  5. C++中的抽象基类示例

    抽象基类(abstract base class,ABC)例子:圆与椭圆.建立一个基类BaseEllipse,建立它的恋歌继承了Ellipse和Circle.ellipse.h #ifndef ELL ...

  6. Oracle12cWindows安装、介绍及简单使用(图文)

    1.下载 地址为:http://www.oracle.com/technetwork/cn/database/enterprise-edition/downloads/index.html 含企业版和 ...

  7. openstack 安装部署

    环境准备 本次搭建的是openstack kilo版本,计算节点和控制节点采用linux bridge的方式连接 1.两台服务器 controller 172.16.201.9 compute01 1 ...

  8. 非旋转Treap

    Treap是一种平衡二叉树,同时也是一个堆.它既具有二叉查找树的性质,也具有堆的性质.在对数据的查找.插入.删除.求第k大等操作上具有期望O(log2n)的复杂度.     Treap可以通过节点的旋 ...

  9. Excel打开csv文件乱码问题的解决办法

    excel打开csv 出现乱码怎么解决 https://jingyan.baidu.com/article/ac6a9a5e4c681b2b653eacf1.html CSV是逗号分隔值的英文缩写,通 ...

  10. 【BZOJ2809】[Apio2012]dispatching 可并堆

    [BZOJ2809][Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 M ...