DOM2事件处理很折腾,每次事件促发时候都会把所有元素遍历两遍,这点和ie事件相比性能就差多了,ie只有冒泡,所以ie只需要遍历一次,不过遍历少了并不代表ie的事件体系效率更高,从开发设计角度同时支持两种事件系统会给我们开发带来更大的灵活度,从这个角度而言DOM2事件还是很有可取之处。DOM2事件的代码如下:
复制代码 代码如下:
var btnDOM = document.getElementById("btn");
btnDOM.addEventListener("click",function(){
alert("Click Me!");
},false);
var ftn = function(){
alert("Click Me,too!");
};
btnDOM.addEventListener("click",ftn,false);
DOM2事件处理里添加事件使用的是addEventListener,它接收三个参数比ie事件处理多一个,前两个的意思和ie事件处理方法的两个参数一样,唯一的区别就是第一个参数里要去掉on这个前缀,第三个参数是个布尔值,如果它的取值是true,那么事件就按照捕获方式处理,取值为false,事件就是按照冒泡处理,有第三个参数我们可以理解为什么DOM2事件处理里要把事件元素跑个两遍,目的就是为了兼容两种事件模型,不过这里要请注意下,不管我们选择是捕获还是冒泡,两遍遍历是永远进行,如果我们选择一种事件处理方式,那么另外一个事件处理流程里就不会促发任何事件处理函数,这和汽车挂空挡空转的道理一样。通过DOM2事件方法的设计,我们知道DOM2事件在运行时候只能执行两种事件处理方式中的一种,不可能两个事件流体系同时促发,所以虽然元素遍历两遍,但是事件函数绝不可能被促发两遍,注意我这里指不促发两遍是指一个事件函数,其实我们可以模拟两个事件流模型同时执行的情况,例如下面代码:
复制代码 代码如下:
btnDOM.addEventListener("click",ftn,true);
btnDOM.addEventListener("click",ftn,false);
但这种写法是多事件处理,相当于我们点击两次按钮。
DOM2也提供了删除事件的函数,这个函数就是removeEventListener,写法如下:
复制代码 代码如下:
btnDOM.removeEventListener("click",ftn,false);
使用和ie事件的一样即参数要和定义事件的参数一致,不过removeEventListener使用时候,第三个参数不传,默认是删除冒泡事件,因为第三个参数不传默认都是false,例如:
复制代码 代码如下:
btnDOM.addEventListener("click",ftn,true);
btnDOM.removeEventListener("click",ftn);
运行之,发现事件没有被删除成功。
最后我要说的是DOM2事件处理在ie9包括ie9以上的版本都得到了很好的支持,ie8以下是不支持DOM2事件的。
下面我们对三种事件方式做个比较,比较如下:
比较一:方式一为一方和其他两种方式比较
方式一的写法是html和javascript结合在一起,你中有我我中有你,把这种方式深化一下就是html和javascript混合开发,用一个软件术语表达就是代码耦合,代码耦合不好,而且是非常不好,这是菜鸟程序员的级别,所以方式一完败,另外两种方式完胜。
比较二:方式二和方式三
它们两个写法差不多,有时真的很难说谁好谁坏,纵观上述内容我们发现方式二和方式三的最大区别就是:使用方式二一个DOM元素某个事件有且只有一次,而方式三则可以让DOM元素某个事件拥有多个事件处理函数,在DOM2事件处理里,方式三还能让我们精确控制事件流的方式,因此方式三的功能比方式二更加的强大,所以相比之下方式三略胜一筹。
下面就是本文的重点:事件系统的性能问题,解决性能问题必须找到一个着力点,这里我从两个着力点来思考事件系统的性能问题,它们分别是:减少遍历次数和内存消耗。
首先是遍历次数,不管是捕获事件流还是冒泡事件流,都会遍历元素,而是都是从最上层的window或document开始的遍历,假如页面DOM元素父子关系很深,那么遍历的元素越多,像DOM2事件处理这种,遍历危害程度就越大了,如何解决这个事件流遍历问题了?我的回答是没有,这里有些朋友也许会有疑问,怎么会没有了?事件系统里有个事件对象即event,这个对象有阻止冒泡或捕获事件的方法,我怎么说没有呢?这位朋友的疑问很有道理,但是如果我们要使用该方法减少遍历,那么我们代码就要处理父子元素的关系,爷孙元素关系,如果页面元素嵌套很多,这就是没法完成的任务,所以我的回答是没法改变遍历的问题,只能去适应它。