测试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 ...
随机推荐
- Android 进程和线程模型
Android进程模型 在安装Android应用程序的时候,Android会为每个程序分配一个Linux用户ID,并设置相应的权限,这样其它应用程序就不能访问此应用程序所拥有的数据和资源了. 在 Li ...
- 转帖:Html.BeginForm
Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...
- Oracle存储过程Procedure语法及案例
create or replace procedure replace(desstr in varchar2, replacestr in varchar2, tablename in varchar ...
- LeetCode 链表的插入排序
Sort a linked list using insertion sort 创建一个新的链表,将旧链表的节点插入到正确的位置 package cn.edu.algorithm.huawei; pu ...
- UVA 674 Coin Change(dp)
UVA 674 Coin Change 解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87730#problem/ ...
- php随笔4-thinkphp 学习-ThinkPHP3.1快速入门(2)数据CURD
ThinkPHP3.1快速入门(2)数据CURD 浏览:194739 发布日期:2012/09/05 分类:文档教程 关键字: 快速入门 CURD 上一篇中,我们了解了ThinkPHP的基础部分, ...
- python成长之路9——socket和socketserver
IPC:进程间通信 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具 ...
- IE读取并显示本地图像文件的方法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- java学习之字符流与字节流的转换
package com.io; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundExce ...
- swift菜鸟入门视频教程-07-闭包
本人自己录制的swift菜鸟入门,欢迎大家拍砖.有什么问题能够在这里留言. 主要内容: 闭包表达式(Closure Expressions) 跟随闭包(Trailing Closures) 值捕获(C ...