关于编写性能高效的javascript事件的技术(2)

在页面开发里我们常常会碰到这样的情况,一个页面的工作区间在javascript可以用document表示,页面里有个div,div等于是覆盖在document元素上,div里面有个button元素,button元素是覆盖在div上,也等于覆盖着document上,所以问题来了,当我们点击这个按钮时候,这个点击行为其实不仅仅发生在button之上,div和document都被作用了点击操作,按逻辑这三个元素都是可以促发点击事件的,而事件流正是描述上述场景的概念,事件流的意思是:从页面接收事件的顺序。

第二个概念:事件冒泡和事件捕获

事件冒泡是微软公司提出解决事件流问题的方案,而事件捕获则是网景公司提出的事件流解决方案,它们的原理如下图:

关于编写性能高效的javascript事件的技术

冒泡事件由div开始,其次是body,最后是document,事件捕获则是倒过来的先是document,其次是body,最后是目标元素div,相比之下,微软公司的方案更加人性化符合人们的操作习惯,网景的方案就很别扭了,这是浏览器大战的恶果,网景慢了一步就以牺牲用户习惯的代码解决事件流的问题。

微软公司结合冒泡事件设计了一套新的事件系统,业界习惯称为ie事件处理,ie事件处理方式如下面代码所示:

复制代码 代码如下:


var btnDOM = document.getElementById("btn");
btnDOM.attachEvent("onclick",function(){
         alert("Click Me!");
});

在ie下通过DOM元素的attachEvent方法添加事件,和DOM0事件处理相比,添加事件的方式由属性变成了方法,所以我们添加事件就需要往方法里传递参数,attachEvent方法接收两个参数,第一个参数是事件类型,事件类型的命名和DOM0事件处理里的事件命名一样,第二个参数是事件函数了,使用方法的好处就是如果我们在为同一个元素添加个点击事件,如下所示:

复制代码 代码如下:


btnDOM.attachEvent("onclick",function(){
         alert("Click Me!");
});
btnDOM.attachEvent("onclick",function(){
         alert("Click Me,too!");
});

运行之,两个对话框都能正常弹出来,方法让我们可以为DOM元素添加多个不同的点击事件。如果我们不要某个事件呢?我们该怎么做了,ie为删除事件提供了detachEvent方法,参数列表和attachEvent一样,如果我们要删除某个点击事件,只要传递和添加事件一样的参数即可,如下代码所示:

复制代码 代码如下:


btnDOM.detachEvent("onclick",function(){
         alert("Click Me,too!");
});

运行之,后果很严重,我们很迷惑,第二个click居然没有被删除,这是怎么回事?前面我讲到删除事件要传入和添加事件一样的参数,但是在javascript的匿名函数里,两个匿名函数哪怕代码完全一样,javascript都会在内部使用不同变量存储,结果就是我们看到的现象无法删除点击事件的,因此我们的代码要这么写:

复制代码 代码如下:


var ftn = function(){
         alert("Click Me,too!");
};
btnDOM.attachEvent("onclick",ftn);
btnDOM.detachEvent("onclick",ftn);

这样添加的方法和删除的方法就是指向了同一个对象,所以事件删除成功了。这里的场景告诉我们写事件要有个良好的习惯即操作函数要独立定义,不要用匿名函数用成了习惯。

接下来就是DOM2事件处理,它的原理如下图所示:

关于编写性能高效的javascript事件的技术

DOM2是标准化的事件,使用DOM2事件,事件传递首先从捕获方式开始即从document开始,再到body,div是一个中介点,事件到了中介点时候事件就处于目标阶段,事件进入目标阶段后事件就开始冒泡处理方式,最后事件在document上结束。(捕获事件的起点以及冒泡事件的终点,我本文都是指向document,实际情况是有些浏览器会从window开始捕获,window结束冒泡,不过我觉得开发时候不管浏览器本身怎么设定,我们关注document更具开发意义,所以我这里一律都是使用document)。人们习惯把目标阶段归为冒泡的一部分,这主要是因为开发里冒泡事件使用的更加广泛。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgswyg.html