测试DOM0级事件和DOM2级事件的堆叠
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级事件的堆叠的更多相关文章
- DOM1级问题与DOM2级事件
前几天有小伙伴问过我一个问题,为什么有DOM 0级事件以及DOM2级事件,但是却没有DOM1级事件呢?那我们今天就来说一说DOM的级别问题. 同时推荐伙伴们可以看看尚学堂有关JavaScript BO ...
- dom0级事件和dom2级事件
dom0级事件 <a href="#" id="hash" onclick="fn();fn1();"> <button ...
- 【20190226】JavaScript-知识点记录:dom0级事件,dom2级事件
DOM0级事件处理程序: 通过将元素的事件处理程序属性(如onclick)的值设置为一个函数来指定事件处理程序的方法称为DOM0级方法,它被认为是元素的方法,这时候的事件处理程序是在元素的作用域中运行 ...
- 关于DOM事件流、DOM0级事件与DOM2级事件
一.DOM 事件模型 DOM 事件模型包括捕获和冒泡,捕获是从上往下到达目标元素,冒泡是从当前元素,也就是目标元素往上到 window 二.流 流的概念,在现今的 JavaScript 中随处可见.比 ...
- js DOM0级事件和DOM2级事件
注册事件有两种方式,分别是DOM0级和DOM2级 DOM0级就是通过事件绑定的形式dom元素只能有(绑定)一个事件处理函数,他的特点是同一个元素绑定相同事件, 后面函数会覆盖前面的 绑定: dom.o ...
- DOM0级事件处理、DOM2级事件处理
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 关于DOM2级事件的事件捕获和事件冒泡
DOM2级事件中addEventListener的执行机制,多个addEventListener同时添加时的执行先后规律: W3C的DOM事件触发分为三个阶段:①.事件捕获阶段,即由最顶层元素(一般是 ...
- JavaScript 之默认行为 DOM2级,事件委托机制
1. 事件默认行为及阻止方式 1.1 浏览器的默认行为 JavaScript事件本身所具有的属性,例如a标签的跳转,Submit按钮的提交,右键菜单,文本框的输入等. 1.2 ...
- javaScript——DOM1级,DOM2级,DOM3级
DOM0,DOM2,DOM3事件处理方式区别:http://www.qdfuns.com/notes/11861/e21736a0b15bceca0dc7f76d77c2fb5a.html JS中do ...
随机推荐
- HDOJ 1427(dfs) 速算24点
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1427 思路分析: 题目要求判断是否存在一种运算组合使得4个数的计算结果为24,因为搜索的层次为3层,不 ...
- Android多线程断点续传下载
这个月接到一个项目.要写一个像360助手一样的对于软件管理的APP:当中.遇到了一个问题:多线程断点下载 这个 ,因为之前没有写过这方面的应用功能.所以.不免要自学了. 然后就在各个昂站上收索并整理了 ...
- 84. 从视图索引说Notes数据库(下)
作用和代价上文介绍了关系型数据库里的索引.Notes数据库里的索引隐藏在视图概念里(本文的讨论仅仅针对Notes的视图索引,不包括全文索引.).开发者创建的视图仅仅是存放在数据库里的一条设计文档.数据 ...
- python编写工具及配置(notepad++)
学长跟我说老师实验室里用的ide是pycharm,我用了一天,整体还行,就是加载速度太慢,可是第二天用的时候就卡的想让人骂街,cpu占有率趋近100%,电脑配置不高,我寻思不能因为这个就马上换电脑吧, ...
- VMware: linux起步提示 memory for crashkernel(0*0 to 0*0)not within permissible
(virtualbox/VMware)linux起步提示memoryforcrashkernel(0*0 to 0*0)notwithinpermissible http://www.myexcep ...
- MD5校验及其c实现
那么MD5校验是什么? 一般软件或者说文件都有自己的固定文件格式或者架构信息,说简单一点就是.”世界上没有完全相同的2片叶子” ,因为MD5是一种不可逆的加密算法. 那么对于某些网上公开下载的软件,视 ...
- Qt 5.2.0 和 VS 2012集成
下载两个安装包,后面一个add-in是必需的 Qt 5.2.0 for Windows 64-bit (VS 2012, 590 MB) (Info) Visual Studio Add-in 1.2 ...
- LNMP安装包sh脚本
Xshell 5 (Build 0719) Copyright (c) 2002-2015 NetSarang Computer, Inc. All rights reserved. Type `he ...
- 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)
原文 教你怎么用Mono Cecil - 动态注入 (注意代码的注释) 使用 Mono Cecil 进行反编译:using Mono.Cecil; using Mono.Cecil.Cil; //.. ...
- JAVA排序(二) Comparator接口
接着说关于Comparator接口, java.util Interface Comparator<T>(该泛型指定的是被比较的类),使用该接口不需要在待比较类进行比较操作,即在不修改源码 ...