js自定义事件及事件交互原理概述(二)


Posted in Javascript onFebruary 01, 2013

js自定义事件(一)的目的只是让大家简单的理解自定事件是如何模拟出来的,大家不难发现会有很多缺陷,比如:
1、此事件对象只能注册一个事件,不能提供多个事件
2、注册方法没有返回的一些信息

下面我们就来解决这些问题。如下为MyEvent.js源代码:

function MyEvent(){ 
this.handlers={}; 
} 
MyEvent.prototype={ 
addHandler:function(type,handler) 
{ 
if(typeof this.handlers[type]=="undefined") 
{ 
this.handlers[type]=[]; 
} 
this.handlers[type].push(handler); 
}, 
fire:function(event) 
{if(this.handlers[event.type] instanceof Array) 
{ 
var handlers=this.handlers[event.type]; 
for(var i= 0, len=handlers.length;i<len;i++) 
{ 
handlers[i](event); 
} 
} 
}, 
removeHandler:function(type,handler) 
{ 
if(this.handlers[type] instanceof Array) 
{ 
var handlers=this.handlers[type]; 
for(var i= 0, len=handlers.length;i<len;i++) 
{ 
if(handlers[i]===handler) 
{ 
break; 
} 
} 
handlers.splice(i,1); 
} 
} 
};

此类就是对第一篇的优化。
属性handler变成了handlers,变成了一个数组
addHandler()方法接受两个参数:事件类型和用于处理该事件的函数。当调用该方法时,会进行一次检查,看看handlers属性中是否已经存在一个针对该事件类型的数组
;如果没有,则创建一个新的。然后使用push()将该处理程序添加到数组的末尾。

fire()方法用于触发一个事件,该方法接受一个参数,是一个至少包含type属性的对象,不然无法确定handlers里面是否已经存在。它会通过此type去查找对应该事件类型的一组处理程序,调用各个函数,并给出event对象。因为这些都是自定义对象,所以event对象上面的其他东西可以由你自己定义。

removeHandler()方法时addHandler()的辅助,它们接受的参数一样:事件的类型和事件处理程序。这个方法搜索事件处理程序的数组找到要删除的处理程序的位置。如果找到了,则使用break操作符退出循环。然后使用splice()方法将该项目从数组中删除。

这里使用方式我们换一种比较长用的形式,现在据我说知很多产品在使用事件上有两种方式,一种是直接继承(js本省没有此概念,不过我们可以通过原型链模拟出继承的效果,此处不做详细解释)此事件对象,那么就会拥有了这些行为,不过此方法比较局限,另一种方式更常用一些,就是需要使用事件的类上面创建一个属性用于存放此对象。如:子相同目录下再创建一个Student.js文件,里面的代码如下:

function Student(name) 
{ 
this.myEvent=new MyEvent(); 
this.name=name; 
} 
Student.prototype={ 
setName:function(name) 
{ 
var eventStart={ 
type:"changeNameStart", 
newName:name, 
oldName:this.name 
}; 
this.myEvent.fire(eventStart); 
this.name=name; 
} 
}

这里有一个学生类,构造函数里面初始化一个MyEvent对象作为属性,通过参数初始化name属性。

提供一个方法setName用于改变名字,不过在改变名字之前设置了可能触发事件changNameStart的监听。
创建一个html页面,放于同个目录下,代码如下:

<html> 
<head> 
<title></title> 
<script type="text/javascript" src="MyEvent.js"></script> 
<script type="text/javascript" src="Student.js"></script> 
<script type="text/javascript"> 
function init() 
{ 
 //初始化一个学生对象 
var student=new Student("Mr liu"); 
 //注册事件changNameStart 
student.myEvent.addHandler("changeNameStart",myMethod); 
//设置name,将会触发事件changNameStart 
student.setName("Mr Huang"); 
} 
function myMethod(e) 
{ 
alert("事件类型:"+e.type+"; 改变前的名字:"+ e.oldName+"; 改变后的名字:"+ e.newName); 
} 
</script> 
</head> 
<body> 
<input type="button" onclick="init()" value="测试" /> 
</body> 
</html>

这样使用起来就会很方便,也是一种常用的使用方式。
一般在真正的项目里面使用使用事件时我们还需要做一些优化,比如:
1、用户并不知道我们提供了哪些事件,从代码来看好像什么事件都可以添加到handlers里面,但是真正起效果的(我们设置fire()方法的地方)事件我们并不能从代码里面很直观的看出来,一般做产品,在这方面都需要再做考虑。

2、有没有发现fire的参数event好像没用固定,在大兴项目里面,最好event也做成一个类型,在fire的地方就比较方便使用一些,event可能会有很多种类型,那时可能fire里面会出现一些判定了。
希望对初入js事件的读者有所帮助,互相交流。

Javascript 相关文章推荐
jQuery Ajax 仿AjaxPro.Utility.RegisterTypeForAjax辅助方法
Sep 27 Javascript
通过正则格式化url查询字符串实现代码
Dec 28 Javascript
尝试在让script的type属性等于text/html
Jan 15 Javascript
JavaScript 函数replace深入了解
Mar 14 Javascript
JS如何判断移动端访问设备并解析对应CSS
Nov 27 Javascript
JavaScript中window.open用法实例详解
Apr 15 Javascript
jQuery实现Tab菜单滚动切换的方法
Sep 21 Javascript
jQuery实现div随意拖动的实例代码(通用代码)
Jan 28 Javascript
javascript设置文本框光标的方法实例小结
Nov 04 Javascript
js封装成插件_Canvas统计图插件编写实例
Sep 12 Javascript
JS扩展String.prototype.format字符串拼接的功能
Mar 09 Javascript
仿vue-cli搭建属于自己的脚手架的方法步骤
Apr 17 Javascript
js自定义事件及事件交互原理概述(一)
Feb 01 #Javascript
js解析与序列化json数据(三)json的解析探讨
Feb 01 #Javascript
js解析与序列化json数据(二)序列化探讨
Feb 01 #Javascript
js解析与序列化json数据(一)json.stringify()的基本用法
Feb 01 #Javascript
百度地图api应用标注地理位置信息(js版)
Feb 01 #Javascript
jquery select动态加载选择(兼容各种浏览器)
Feb 01 #Javascript
表单元素的submit()方法和onsubmit事件应用概述
Feb 01 #Javascript
You might like
一条久听不愿放下的DIY森海MX500,三言两语话神奇
2021/03/02 无线电
php编写一个简单的路由类
2011/04/13 PHP
PHP通过正则表达式下载图片到本地的实现代码
2011/09/19 PHP
php递归使用示例(php递归函数)
2014/02/14 PHP
thinkPHP5框架实现基于ajax的分页功能示例
2018/06/12 PHP
js 加载时自动调整图片大小
2008/05/28 Javascript
通过JS动态创建一个html DOM元素并显示
2014/10/15 Javascript
使用js实现的简单拖拽效果
2015/03/18 Javascript
详解 javascript中offsetleft属性的用法
2015/11/11 Javascript
JavaScript面试题大全(推荐)
2016/09/22 Javascript
jquery表单插件form使用方法详解
2017/01/20 Javascript
vue动态组件实现选项卡切换效果
2017/03/08 Javascript
Angular设置别名alias的方法
2018/11/08 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
Cpy和Python的效率对比
2015/03/20 Python
python实现复制整个目录的方法
2015/05/12 Python
Python多进程分块读取超大文件的方法
2016/04/13 Python
深入浅出学习python装饰器
2017/09/29 Python
python 打印直角三角形,等边三角形,菱形,正方形的代码
2017/11/21 Python
python实现图片彩色转化为素描
2019/01/15 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
2020/09/17 Python
Pandas实现一列数据分隔为两列
2020/05/18 Python
使用python实现下载我们想听的歌曲,速度超快
2020/07/09 Python
详解HTML5 canvas绘图基本使用方法
2018/01/29 HTML / CSS
html5指南-2.如何操作document metadata
2013/01/07 HTML / CSS
中专生自荐信
2013/10/12 职场文书
办公室文秘岗位职责
2013/11/15 职场文书
专科应届生求职信
2013/11/24 职场文书
财务管理职业生涯规划书
2014/02/26 职场文书
写求职信要注意什么问题
2014/04/12 职场文书
审计局班子四风对照检查材料思想汇报
2014/10/07 职场文书
2015年关爱留守儿童工作总结
2015/05/22 职场文书
闪闪红星观后感
2015/06/08 职场文书
Go标准容器之Ring的使用说明
2021/05/05 Golang
基于Redis6.2.6版本部署Redis Cluster集群的问题
2022/04/01 Redis
Windows Server 2016服务器用户管理及远程授权图文教程
2022/08/14 Servers