1. 问题

如果大家看过北风网CJ讲师的Javascript视频教程,就可以看到其封装了一个很强的事件添加和删除函数,如下所示

  function addEvent(obj, evtype, fn) {
//符合W3C的事件模型
if (obj.addEventListener) {
obj.addEventListener(evtype,fn,false);
return obj;
} //IE或Opera浏览器
if (!obj.functions) obj.functions={};
if (!obj.functions[evtype])
obj.functions[evtype] = []; var functions=obj.functions[evtype];
for (var i=0;i<functions.length;i++) {
if (functions[i] === fn) return obj;
}
functions.push(fn); if (typeof obj["on"+evtype]=="function") {
if (obj["on"+evtype]!=handler)
functions.push(obj["on"+evtype]);
}
obj["on"+evtype]=handler;
return obj;
} function delEvent(obj,evtype,fn) {
if (obj.removeEventListener) {
obj.removeEventListener(evtype,fn,false);
return obj;
}
var fns=obj.functions || {};
fns=fns[evtype] || [];
for (var i=0;i<fns.length;i++) {
if (fns[i]==fn) {
fns.splice(i,1);
return obj;
}
}
}

它因为各种原因,没有采用IE的DOM2级事件添加函数attachEvent,以期达到非常完美的兼容性,据说可以到 IE5.5 或以下。分析代码页可以看到,它通过给DOM元素添加一个以 on + ‘type’ 为名的属性,其对应的值是一个处理函数的数组,本质来说就是仅仅利用 DOM0级提供的接口 elem.onclick = function () { ...} 来添加事件。

一直以来没有发现什么问题,直到给别人使用时,发现IE6~8通过该封装函数 addEvent 添加的 load 事件并没有执行,调试代码发现别人在 JS 中通过 window.onload 赋了一个处理函数,顿时明白这种 addEvent 封装的一个大Bug,原因很简单,通过DOM0级提供的事件接口多次添加时,后面的函数会覆盖前面的,而这种 addEvent 本质上就是一个 DOM0级函数,所以肯定会被后面的覆盖。

也就是说, addEvent 是假定网页JS代码中不使用 DOM0级添加事件。

2. 构建测试页面和代码

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<script src="dom.event.js"></script>
<title>测试DOM0级事件和DOM2级事件的堆叠</title>
</head>
<body>
<textarea name="have" id="output" cols="30" rows="10"></textarea> <button id="testBtn">测试</button> <script type="text/javascript">
var btn = document.getElementById('testBtn');
var output = document.getElementById('output'); // 标准的 DOM2 级事件添加方法
// if (btn.addEventListener) {
// btn.addEventListener('click', function () {
// output.value += 'DOM 2 Level Click\r\n';
// });
// } else {
// btn.attachEvent('onclick', function () {
// output.value += 'DOM 2 Level Click\r\n';
// })
// } // 使用封装的 addEvent 函数
// addEvent(btn, 'click', function () {
// output.value += 'DOM 2 Level Click\r\n';
// }); btn.onclick = function () {
output.value += 'DOM 0 Level Click 111111\r\n';
} btn.onclick = function () {
output.value += 'DOM 0 Level Click 222222\r\n';
} </script>
</body>
</html>

测试1:点击测试按钮,可以看到textarea 中只是输出 DOM 0 Level Click 22222 信息,也就是后面添加的事件覆盖了之前添加的,跟变量赋值是一个道理!!

测试2:将 DOM2 级事件添加的代码反注释掉,打开网页点击测试按钮,可以看到会输出 DOM 2 Level Click 和 DOM 0 Level Click 22222,也就是说DOM0 级事件和 DOM2 级添加的事件都会处理,DOM0级并不会覆盖 DOM2 添加的事件处理函数。

测试3: 将 DOM2 级事件保持注释状态,反注释掉 addEvent 部分, 可以看到只会输出 DOM 0 Level Click 22222。

测试4: 在测试3 的基础上, 注释掉后面两个 DOM0 级添加事件的代码,以测试 addEvent 的输出,可以看到它输出 DOM 2 Level Click, 从而证明测试3中其被覆盖的结论。

3. 总结

  1) DOM0 级事件和 DOM2 级事件可以共存;

  2) 尽量不要写 DOM0 级事件,特别是代码提供给别人使用时,绝对不能写!

测试DOM0级事件和DOM2级事件的堆叠的更多相关文章

  1. DOM1级问题与DOM2级事件

    前几天有小伙伴问过我一个问题,为什么有DOM 0级事件以及DOM2级事件,但是却没有DOM1级事件呢?那我们今天就来说一说DOM的级别问题. 同时推荐伙伴们可以看看尚学堂有关JavaScript BO ...

  2. dom0级事件和dom2级事件

    dom0级事件 <a href="#" id="hash" onclick="fn();fn1();"> <button ...

  3. 【20190226】JavaScript-知识点记录:dom0级事件,dom2级事件

    DOM0级事件处理程序: 通过将元素的事件处理程序属性(如onclick)的值设置为一个函数来指定事件处理程序的方法称为DOM0级方法,它被认为是元素的方法,这时候的事件处理程序是在元素的作用域中运行 ...

  4. 关于DOM事件流、DOM0级事件与DOM2级事件

    一.DOM 事件模型 DOM 事件模型包括捕获和冒泡,捕获是从上往下到达目标元素,冒泡是从当前元素,也就是目标元素往上到 window 二.流 流的概念,在现今的 JavaScript 中随处可见.比 ...

  5. js DOM0级事件和DOM2级事件

    注册事件有两种方式,分别是DOM0级和DOM2级 DOM0级就是通过事件绑定的形式dom元素只能有(绑定)一个事件处理函数,他的特点是同一个元素绑定相同事件, 后面函数会覆盖前面的 绑定: dom.o ...

  6. DOM0级事件处理、DOM2级事件处理

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 关于DOM2级事件的事件捕获和事件冒泡

    DOM2级事件中addEventListener的执行机制,多个addEventListener同时添加时的执行先后规律: W3C的DOM事件触发分为三个阶段:①.事件捕获阶段,即由最顶层元素(一般是 ...

  8. JavaScript 之默认行为 DOM2级,事件委托机制

    1. 事件默认行为及阻止方式    1.1 浏览器的默认行为       JavaScript事件本身所具有的属性,例如a标签的跳转,Submit按钮的提交,右键菜单,文本框的输入等.    1.2 ...

  9. javaScript——DOM1级,DOM2级,DOM3级

    DOM0,DOM2,DOM3事件处理方式区别:http://www.qdfuns.com/notes/11861/e21736a0b15bceca0dc7f76d77c2fb5a.html JS中do ...

随机推荐

  1. projecteuler----&gt;problem=8----Largest product in a series

    title: The four adjacent digits in the 1000-digit number that have the greatest product are 9 9 8 9 ...

  2. JS于,子类调用父类的函数

    概要 JS虽然没有直接有面向对象的特性,但还是能prototype为了模拟面向对象的特性,如继承和多态.而大多数面向对象的语言(例如C++.Java等一下)相比,JS为了实现面向对象还是有点繁琐,抽象 ...

  3. 也谈.NET MVC 2 + ExtJS的部署问题

    由于业务需要,笔者刚进到一个项目组,由于没有美工,前台采用ExtJs + MVC 2 ,迭代1的项目做的还算比较顺利,至少在本机上是运行没有任何问题的, 但是为了给客户演示,我兴高采烈的将网站部署在I ...

  4. 简单字符串模式匹配算法的C++实现

    /* * simpleIndex.cpp * Author: Qiang Xiao * Time: 2015-07-13 */ #include<iostream> #include< ...

  5. 裸机离奇事件:Freescale usb 有关fault

    裸机离奇事件:Freescale usbucosiiFreescale\KSDK_1.2.0\examples\twrk65f180m\demo_apps\usb\host\cdc\cdc_seria ...

  6. C++对C语言的非面向对象特性扩充(1)

    我将分3篇来介绍C++相对于C在非对象特性上的扩充,今天要讲的是C++在注释,输入输出,局部变量说明的扩充,以及const修饰符与C中的#define的比较. 1.C++注释除了包括原有C的块注释/* ...

  7. BZOJ 1600: [Usaco2008 Oct]建造栅栏( dp )

    QAQ我没读过书...四边形都不会判定了 简单的dp.... --------------------------------------------------------------------- ...

  8. python安装zlib一直无效

    一直按网上的方法: 1.先安装 apt-get install zlib1g-dev 2.重新安装python(3.3):即是./configure 再make再make install 始终没有解决 ...

  9. BULK SQL

    DECLARE TYPE TY_EMP IS TABLE OF EMP%ROWTYPE; --如果是IS TABLE OF行类型(ROWTYPE.RECORD等)就是二维 V_Emp TY_EMP; ...

  10. C语言之自守数

    自守数 自守数是指一个数的平方的尾数等于该数自身的自然数,如25*25=625,76*76=5776.要求求出一定范围内的所有自守数. 题目分析: 刚拿到这个题目的时候认为解题关键在于,测试该数平方数 ...