你的位置:首页 > Java教程

[Java教程]JavaScript中的事件


最近一段时间正在对JavaScript进行学习,知识太多,需要进行实际的使用和总结,国庆长假正好有时间,写了下面对JavaScript总结,可能对事件的理解还不够完善,希望读者多多指导,拍砖,我将不胜感激。好了直接如题吧。

JavaScript中的事件流

DOM2级事件规定事件流分为3个阶段:

第一阶段:事件捕获阶段,先由文档的根节点Window->Document->html->body…往事件触发对象,从外向内捕获事件对象。

第二阶段:目标阶段,到达目标事件位置,触发事件;

第三阶段:事件冒泡,再从目标事件位置往文档的根节点方向,反向冒泡。

事件捕获和事件冒泡的先后顺序如上图显示的步骤(1)、(2)、(3)。

在此简单的做一下上面的捕获和冒泡的实验:

环境就以常用的Chrome浏览器,代码如下:

 1 <!DOCTYPE html> 2 <html> 3 <head> 4   <title>Event</title> 5 </head> 6 <body> 7   <div id="btn-big-test"> div1 8     <br/> 9     <br/>10     <div id="btn-big-test2">div2</div>11   </div>12 </body>13 <script type="text/javascript">14 var el = document.getElementById('btn-big-test');15 var el2 = document.getElementById('btn-big-test2');16 el.addEventListener('click', function(event) {17   console.log("冒泡1>>" + Date.parse(new Date()));18 }, false);19 20 el.addEventListener('click', function() {21   console.log("捕获1>>" + Date.parse(new Date()));22 }, true);23 el2.addEventListener('click', function() {24   console.log("冒泡2>>" + Date.parse(new Date()));25 }, false);26 27 el2.addEventListener('click', function() {28   console.log("捕获2>>" + Date.parse(new Date()));29 }, true);

View Code

运行结果如下如下:

 

 

看来结果却不是我们想象的那样 先执行捕获在执行冒泡,那么问题来了,是什么问题。想了下不如把下面两个注册事件换一下顺序:

1 el2.addEventListener('click', function() {2   console.log("捕获2>>" + Date.parse(new Date()));3 }, true);4 5 el2.addEventListener('click', function() {6   console.log("冒泡2>>" + Date.parse(new Date()));7 }, false);

View Code

运行结果如下:

现在好了,运行的结果和想象的一样,那么之前怎么会不一样的呢?顺便把这几个全部的顺序都换一下,发现无论怎么换 “捕获1”都会先打印出来,但是事件触发的元素的捕获和冒泡的事件会因为顺序不一样而不同。

由此可见:事件流确实是先由外向内先捕获,在向外冒泡,触发的元素这不同,触发元素是事件的目标元素,那么它的捕获和触发呢,那就是根据事件注册的先后顺序不同来执行的。

说完了事件流的流程,再来说下事件的触发吧。

事件是用户或浏览器自身执行的某种动作。如click、load和mouseover,都是事件的名字,而响应某个事件执行的函数就是事件处理程序,那么怎么进行事件绑定了,其实上面已经有了,

(1)、执行 addEventListener(‘click’,function(){}, false),就表示注册了一个click事件。

(2)、在html 标签中使用 onclick=”yourfunction()” 这个是最常见的方式。

如果你发现addEventListener在ie里面注册不了事件,这是因为IE不同需要采用attachEvent ('onclick', function(){}) 来绑定事件

(3)事件移除则使用removeEventListener或detachEvent。

在此我们已经知道了如何给元素绑定事件,那么触发事件对象中包含哪些内容呢?

 

事件类型

UI事件、焦点事件、鼠标事件、滚轮事件、文本事件、键盘事件、合成事件、变动事件、变动名称事件。暂时不做详细总结,下次待完善…

内存和性能

在JS的世界里,每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。事实上,从如何利用好事件程序的角度出发,还是有一些方法能够提升性能的。

对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。例如,click事件会一直冒泡到Document层次。也就是说我们可以为整个页面指定一个onclick事件处理程序,不必每个元素添加处理事件。多个元素点击的事件合并根据event.target.id来确定处理逻辑,这样虽然代码处理函数变长,但是消耗会更低。如果可行是否可以在document对象添加一个事件处理程序,用于处理页面的某种特定类型的事件,

(1)、Doucument对象很快就可以访问,而且可以在页面生命周期的任何时间点上为它添加程序(无须等待DOMContentLoaded或load事件)。也就是说,只要可点单击的元素呈现在页面上,就可以立即具备适当的功能。

(2)、在页面中设置事件处理程序所需的时间更少。只添加一个事件处理程序所需的DOM应用更少,所花的时间也更少。

(3)、整个页面占用的内存空间更少,能够提升整体性能。

但是也要避免绑定的函数对象过大,适可而止。

事件模拟

采用js在任意时刻来触发特定的事件,如同浏览器创建的事件一样。

DOM中的事件模拟分为UIEvents、MouseEvents、MutationEvents、HTMLEvents,暂时不做详细总结,下次待完善…

好了今天事件总结的最后一个内容了,自定义事件

事件是一种观察者的设计模式,一种松散耦合代码的技术。对象可以发布事件,用来表示该对象生命周期中某个时刻到了。然后其他对象可以观察该对象,等待这些时刻到来并通过运行代码来响应。

观察者由两类对象组成:主体和观察者,主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。事件处理代码便是观察者 DOM元素则是主体,通过注册事件进行注册回调函数(事件处理程序)。

当代码中存在多个部分在特定时刻相互交互的情况下,自定义事件就很有用。这时,如果每个对象都有对所有对象的引用,那么整个代码就会紧耦合,维护困难,因为对某个对象的修改也会影响到其他对象。使用自定义事件有助于解耦相关对象,保持功能的隔绝。很多情况中,触发事件的代码和监听事件的代码是完全分离的。

下面给出一个代码例子

 1 function EventTarget(){ 2   this.handlers={}; 3 } 4  5 EventTarget.prototype={ 6   constructor:EventTarget, 7   addHandler:function(type,handler){ 8     if(typeof this.handlers[type] == "undefined"){ 9       this.handlers[type]=[];10     }11     this.handlers[type].push(handler);12   },13   fire:function(event){14     if(!event.target){15       event.target=this;16     }17     if(this.handlers[event.type] instanceof Array){18       var handlers=this.handlers[event.type];19       for(var i=0,len=handlers.length;i<len;i++){20         handlers[i][event];21       }22     }23 24   },25   removeHandler:function(type,handler){26     if(this.handlers[type] instanceof Array){27       var handlers=this.handlers[type];28       for(var i=0,len=handlers.length;i<len;i++){29         if(handlers[i]=== handler){30           break;31         }32       }33       handlers.splice(i,1);34 35     }36   }37 };

View Code
 1 使用EventTarget类型的自定义事件可以如下使用: 2 function handleMessage(event){ 3   alert("Message received:"+event.message); 4 } 5 //创建一个新对象 6 var target = new EventTarget(); 7 //添加一个事件处理程序 8 target.addHandler("message",handleMessage); 9 //触发事件10 target.fire({type:"message",message:"Hello World"});11 //删除事件处理程序12 target.removeHandler("message",handleMessage);13 //再次,应没有处理程序14 target.fire({type:"message",message:"hello world"});

View Code

到此我所理解的事件基本上算是总结完啦,有些部分还没有总结出来,后面有时间再做详细的总结学习。

参考资料:

(1)、《JavaScript高级程序设计》第3版

(2)、w3c:https://www.w3.org/TR/DOM-Level-3-Events/#ui-events-intro

  




7月泰国旅游泰国旅游多少钱一人泰国游费用泰国旅游团购泰国蜜月旅游最小众的绝美旅行目的地榜单(全文) 为了讨好中国游客 老牌资本主义国家也是蛮拼的 出去旅游买什么?看后再买绝对不亏!(全文) 东莞梦幻百花洲冬季好玩吗?梦幻百花洲冬季景色怎么样? 四川光雾山 醉人秋色画中游 三亚古今来蜡像馆地址?古今来蜡像馆自驾游线路? 古今来趣味蜡像馆几点开门?三亚古今来趣味蜡像馆营业时间? 三亚西岛大学生门票多少钱?西岛大学生有优惠吗? 思罗河漂流刺激吗?石表山思罗河漂流图片? 马拉湾水上乐园电话?郑州马拉湾水上乐园电话谁知道? 思罗河漂流多大孩子可以玩?石表山思罗河漂流儿童怎么收费? 思罗河漂流是通票吗?石表山思罗河漂流进门有其他收费吗? 中秋节去华南植物园有什么活动?广州华南植物园优惠活动介绍? 2015长隆野生动物园中秋节活动?广州长隆野生动物园中秋节门票多少钱? 长隆欢乐世界中秋票价?中秋节去广州长隆欢乐世界有什么活动? 锦绣中华夜场泼水节门票在哪预订?哪里有深圳锦绣中华泼水节优惠票? SL03A1-C1SRWA Datasheet SL03A1-C1SRWA Datasheet SL03A1-C1YWA Datasheet SL03A1-C1YWA Datasheet SL03A1-E1EWA Datasheet SL03A1-E1EWA Datasheet 盂兰盆会 盂兰盆会 盂兰盆会 颐和园地址 颐和园地址 颐和园地址 鼓浪屿手绘地图 鼓浪屿手绘地图 鼓浪屿手绘地图