- 浏览: 315352 次
- 性别:
文章分类
最新评论
-
i042416:
分析在哪?
angular分析 -
何盆盆:
你好,请问您这是Extjs3还是Extjs4
ExtJs源码分析与学习—ExtJs事件机制(一) -
124753561:
引用引用引用引用引用[u][u][u][u][i][i][i] ...
Subvision SVN 服务端与客户端的安装 -
谷超:
请问一下例子中itext是什么版本的?
利用iText生成word文档例子参考 -
geosmart:
正好要用到执行字符串中方法,学习了
java中利用反射机制实现调用给定为字符串的方法名
一、 0 级 DOM 上的事件和 2 级 DOM 事件机制
0 级 DOM 上的事件又称原始事件模型,所有的浏览器都支持他,而且是通用的。 2 级 DOM 事件机制又为标准事件模型,除了 ie 其他浏览器都支持( ie9 也支持), ie 虽然大部分与标准事件模型一样,但有自己专有的事件模型,因此开发人员要实现标准事件模型必须为 IE 写特定的代码,这给程序员增加了负担。
原始事件模型
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>浏览器0级DOM上的事件</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <input type="button" value = "点击我" id = "btn"> </body> </html> <script type="text/javascript"> <!-- var method1 = function(){alert(1)}; var method2 = function(){alert(2)}; var method3 = function(){alert(3)}; document.getElementById("btn").onclick = method1; document.getElementById("btn").onclick = method2; document.getElementById("btn").onclick = method3; //--> </script>
以上书写在各浏览器中都是兼容的,但只有 medhot3 被执行,即同一个对象同一类型的事件只能注册一个处理函数,要想实现注册多个处理函数,需要利用 2 级 DOM 事件机制。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>浏览器2级DOM事件机制</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <input type="button" value = "点击我" id = "btn"> </body> </html> <script type="text/javascript"> <!-- var method1 = function(){alert(1)}; var method2 = function(){alert(2)}; var method3 = function(){alert(3)}; //执行顺序为method1->method2->method3 //标准事件模型 var btn1Obj = document.getElementById("btn"); btn1Obj.addEventListener("click",method1,false); btn1Obj.addEventListener("click",method2,false); btn1Obj.addEventListener("click",method3,false); //执行顺序为method3->method2->method1 //IE事件模型 var btn1Obj = document.getElementById("btn"); btn1Obj.attachEvent("onclick",method1); btn1Obj.attachEvent("onclick",method2); btn1Obj.attachEvent("onclick",method3); //--> </script>
从运行结果来看, ie 和 firefox 下执行的顺序是不一样的
二、2级DOM事件模型事件的注册与删除
element.addEventListener(eventType,fn,useCapture); // 注册事件
element.removeEventListener(eventType,fn, useCapture);// 删除事件
可以用 addEventListener() 给同一个对象同一类型的事件注册多个处理函数,但是如果在同一元素上多次注册了一个处理函数,那么第一次注册后的所有注册都将被忽略,但删除该注册函数(调用 removeEventListener() )后可以再重新注册该函数。需要注意的是删除事件, useCapture 的值必须要跟注册时保持一致
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>浏览器事件机制——注册和删除事件</title> <style> div {border:1px solid blue;} div#div1 {padding:40px;background-color:#aaaaaa;} div#div2 {padding:40px;background-color:#bbbbbb;} div#div3 {padding:40px;background-color:#cccccc;} </style> </head> <body> <div id="div1" style="width:100px;height:100px;" > 我是老大, 点击我添加老三的click事件 </div> <br/> <div id="div2" style="width:100px;height:110px;" > 我是老二, 点击我删除老三的click事件 </div> <br/> <div id="div3" style="width:100px;height:100px;" > 我是老三,是否有click事件,老大老二说了算,呵呵 </div> <script> function click1() { alert("I am div1,add div3 event"); if(window.addEventListener){ div3.addEventListener("click", click3, false); }else if (window.attachEvent){ div3.attachEvent("onclick", click3); } } function click2() { alert("I am div2,remove div3 event"); if(window.addEventListener){ div3.removeEventListener("click", click3, false); }else if (window.attachEvent){ div3.detachEvent("onclick", click3); } } function click3() { alert("I am div3"); } var div1 = document.getElementById("div1"); var div2 = document.getElementById("div2"); var div3 = document.getElementById("div3"); if(window.addEventListener){ div1.addEventListener("click", click1, false); div2.addEventListener("click", click2, false); }else if (window.attachEvent){ div1.attachEvent("onclick", click1); div2.attachEvent("onclick", click2); } </script> </body> </html>
三、2级DOM事件冒泡模型(Bubble Model)
在2级DOM事件模型中,事件传播分三个阶段进行,即捕获阶段(capturing)、目标阶段和冒泡阶段(bubbling)。在捕获阶段,事件从Document对象沿着文档树向下传播给目标节点,如果目标的任何一个祖先(不是目标本身)专门注册了捕获事件句柄,那么在事件传播过程中,就会运行这些句柄,在冒泡阶段,事件将从目标元素向上传播回或气泡回Document对象的文档层次。虽然所有事件都受事件传播的捕获阶段的支配,但并非所有类型的事件都起泡。
在注册事件时,useCapture参数确定侦听器是运行于捕获阶段、目标阶段还是冒泡阶段。 如果将 useCapture 设置为 true,则侦听器只在捕获阶段处理事件,而不在目标或冒泡阶段 处理事件。 如果useCapture 为 false,则侦听器只在目标或冒泡阶段处理事件。 要在所有三个阶段都侦听事件,需调用两次 addEventListener,一次将 useCapture 设置为 true,第二次再将useCapture 设置为 false。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>浏览器事件机制——冒泡处理</title> <style> div {border:1px solid blue;} div#divGrandpa {padding:40px;background-color:#aaaaaa;} div#divFather {padding:40px;background-color:#bbbbbb;} div#divSon {padding:40px;background-color:#cccccc;} </style> </head> <body> <div id="divGrandpa" style="width:300px;height:200px;" > <div id="divFather" style="width:200px;height:120px;" > <div id="divSon" style="width:100px;height:40px;" > 点击我 </div> </div> </div> <script> function showSon() { alert("I am son"); } function showFather() { alert("I am father"); } function showGrandpa() { alert("I am Grandpa"); } var grandpa = document.getElementById("divGrandpa"); var father = document.getElementById("divFather"); var son = document.getElementById("divSon"); if(window.addEventListener){ grandpa.addEventListener("click", showGrandpa, false); father.addEventListener("click", showFather, false); son.addEventListener("click", showSon, false); }else if (window.attachEvent){ grandpa.attachEvent("onclick", showGrandpa); father.attachEvent("onclick", showFather); son.attachEvent("onclick", showSon); } </script> </body> </html>
从运行结果来看,对于ie,在ie(ie8之前的版本,包括ie8)中当点击son节点时,会分别弹出I am son、I am father和I am Grandpa,即事件最先被底层的结点触发,再逐渐上传,直到最外层的结点,冒泡方式为儿子——>父亲的模式;在Firefox等支持标准事件模型的浏览器中,跟addEventListener的Capture参数有关,当设置为true时,为捕获模式,事件会从最顶层的结点往下传输,即 父亲——>儿子的传播模式。当设为false(默认值)时,则会按冒泡模式传递事件。另外由于ie9即支持window.attachEvent,又支持window.addEventListener,所以会根据代码的书写来运行其效果的。
四、如何停止事件的传递
在IE浏览器中可以调用以下代码
event.cancelBubble = true;
在Firefox等遵循W3C规范的浏览器中,可以调用以下代码
e.stopPropagation();
调用以上代码后可以终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点(即不再进一步传播)。
该方法(属性)将停止事件的传播,阻止它被分派到其他 Document 节点。在事件传播的任何阶段都可以调用它。注意,虽然该方法不能阻止同一个 Document 节点上的其他事件句柄被调用,但是它可以阻止把事件分派到其他节点。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>浏览器事件机制——停止事件的进一步传递</title> <style> div {border:1px solid blue;} div#divGrandpa {padding:40px;background-color:#aaaaaa;} div#divFather {padding:40px;background-color:#bbbbbb;} div#divSon {padding:40px;background-color:#cccccc;} </style> </head> <body> <div id="divGrandpa" style="width:300px;height:200px;" > <div id="divFather" style="width:200px;height:120px;" > <div id="divSon" style="width:100px;height:40px;" > 点击我 </div> </div> </div> <script> function showSon(e) { alert("I am son"); } function showFather(e) { //IE把event对象作为window对象的一个属性,而W3C把event对象作为处理程序的一个参数 e = e || event; if(e.stopPropagation){ e.stopPropagation(); }else{ e.cancelBubble = true; } alert("I am father"); } function showGrandpa(e) { alert("I am Grandpa"); } var grandpa = document.getElementById("divGrandpa"); var father = document.getElementById("divFather"); var son = document.getElementById("divSon"); if(window.addEventListener){ grandpa.addEventListener("click", showGrandpa, false); father.addEventListener("click", showFather, false); son.addEventListener("click", showSon, false); }else if (window.attachEvent){ grandpa.attachEvent("onclick", showGrandpa); father.attachEvent("onclick", showFather); son.attachEvent("onclick", showSon); } </script> </body> </html>
以上代码,把useCapture 设为false后,是在冒泡的时候传播事件。当点击son节点时,先执行son注册的事件,再执行father注册的事件,此时该事件中阻止了事件的向上传播,故grandpa注册的事件被阻止。如果把useCapture 设为true后,是在捕获阶段传播事件。当点击son节点时,是先执行grandpa注册的事件,再执行father注册的事件,此时该事件函数中阻止了事件的传播,故son节点注册的事件不会被执行。
五、自定义事件
1、不带参数事件处理,也是最简单的事件设计模式
最简单的一种模式是将一个类的方法成员定义为事件,通常是一个空函数,当程序需要处理该事件时,再进行扩充该事件接口。比如:
function Class1(){ //构造函数 } Class1.prototype = { show : function(){ this.onShow();//触发onShow事件 }, onShow : function(){}//定义事件接口 } //创建class1实例 var obj = new Class1(); //创建obj的onShow事件处理程序 obj.onShow = function(){ alert('onshow event'); } //调用obj的show方法 obj.show();
以上实现,每个事件接口仅能绑定1个事件处理程序
2、给事件处理程序传递参数
//将有参数的函数封装为无参数的函数 function createFunction(obj, strFn){ obj = obj || window; var args = []; for(var i = 2; i < arguments.length; i++){ args.push(arguments[i]); } return function(){ //该语句相当于obj[strFn](args[0],args[1],...); obj[strFn].apply(obj,args); } } //定义类 Class1 function Class1(){ //构造函数 } Class1.prototype = { show : function(){ this.onShow();//触发onShow事件 }, onShow : function(){}//定义事件接口 } //创建class1实例 var obj = new Class1(); //创建obj的onShow事件处理程序 function objOnShow(userName){ alert('hello, ' + userName); } var userName = 'xiaowang'; //绑定obj的onShow事件 obj.onShow = createFunction(null,'objOnShow',userName); //调用obj的show方法 obj.show();
在以上代码中,将变量userName作为参数传递给了objOnShow事件处理程序。事实上,obj.onShow 得到的事件处理程序并不是objOnShow,而是由createFunction返回的一个无参函数
3、自定义事件支持多绑定
//定义类 Class1 function Class1(){ //构造函数 } Class1.prototype = { show : function(){ //如果有事件绑定则循环onshow数组,触发该事件 if(this.onshow){ for(var i = 0, len = this.onshow.length; i < len; i++){ this.onshow[i]();//调用事件处理程序 } } }, addEventOnShow : function (_eHandler){ this.onshow = this.onshow || [];//用数组存储绑定的事件处理程序引用 this.onshow.push(_eHandler); } } //创建class1实例 var obj = new Class1(); //事件一 function onShow1(){ alert('event1'); } //事件二 function onShow2(){ alert('event2'); } //绑定事件 obj.addEventOnShow(onShow1); obj.addEventOnShow(onShow2); //调用obj的show方法 obj.show();
4、自定义事件支持带参数的多绑定
//将有参数的函数封装为无参数的函数 function createFunction(obj, strFn){ obj = obj || window; var args = []; for(var i = 2; i < arguments.length; i++){ args.push(arguments[i]); } return function(){ //该语句相当于obj[strFn](args[0],args[1],...); obj[strFn].apply(obj,args); } } //定义类 Class1 function Class1(){ //构造函数 } Class1.prototype = { show : function(){ //如果有事件绑定则循环onshow数组,触发该事件 if(this.onshow){ for(var i = 0, len = this.onshow.length; i < len; i++){ this.onshow[i]();//调用事件处理程序 } } }, addEventOnShow : function (_eHandler){ this.onshow = this.onshow || [];//用数组存储绑定的事件处理程序引用 this.onshow.push(_eHandler); } } //创建class1实例 var obj = new Class1(); //创建obj的onShow事件处理程序 function objOnShow(userName){ alert('hello, ' + userName); } //事件一 var userName1 = 'xiaowang'; var onShow1 = createFunction(null,'objOnShow',userName1); //事件一 var userName2 = 'xiaoli'; var onShow2 = createFunction(null,'objOnShow',userName2); //绑定事件 obj.addEventOnShow(onShow1); obj.addEventOnShow(onShow2); //调用obj的show方法 obj.show();
以上实现把带参数和多绑定结合在一起,还可以增加一个removeEventOnShow来删除已注册的事件。
六、把对象注册为事件句柄
在编写面向对象的JavaScript程序时,如果想用对象作为事件句柄,那么可以使用如下的函数来注册它们:
function registerObjectEventHandler(element,eventtype,listener,captures){
element.addEventListener(eventtype,
function(event) {listener.handleEvent(event);},captures);
}
用这个函数可以把任何对象注册为事件句柄,只要它定义了handleEvent()方法。Firefox(以及其他基于Mozilla代码的浏览器)允许直接把定义了handleEvent()方法的事件监听器对象传递给addEventListener()方法而不是函数引用。对于这些浏览器来说,不需要我们刚才给出的特殊注册函数。
请看下面的例子
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>把对象注册为事件句柄</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> </head> <body> <input type="button" value = "点击我" id = "btn"> </body> </html> <script type="text/javascript"> <!-- var EventHandler = function(){} EventHandler.prototype.handleEvent = function(event){ alert('用对象作为事件句柄,只要实现该对象的方法handleEvent即可'); alert(event.type); } var objectHandler = new EventHandler(); var btn1Obj = document.getElementById("btn"); if(window.addEventListener){ btn1Obj.addEventListener("click",objectHandler,false); }else if (window.attachEvent){ //btn1Obj.attachEvent("onclick",objectHandler);//调用失败,说明不支持把对象注册为事件句柄 //btn1Obj.attachEvent("onclick",objectHandler.handleEvent); registerObjectEventHandler(btn1Obj,"onclick",objectHandler); } /** * 对于不支持把对象注册为事件句柄的浏览器,可以调用以下方法来实现 */ function registerObjectEventHandler(element,eventtype,listener,captures){ if(window.addEventListener){ element.addEventListener(eventtype, function(event) {listener.handleEvent(event);},captures); }else if (window.attachEvent){ element.attachEvent(eventtype, function(event) {listener.handleEvent(event);}); } } //--> </script>
发表评论
-
angular分析
2014-07-08 13:49 992angular分析 -
键盘KeyCode值列表
2012-08-28 18:13 1049keycode 0 = keycode 1 = k ... -
JavaScript中的delete操作符
2012-04-20 14:17 1442主要从以下几个方面说 ... -
javascript性能优化之一
2012-04-04 21:01 0该篇文章转自 http://blog.sina.com.cn ... -
DOM节点中属性nodeName、nodeType和nodeValue的区别
2012-03-20 17:31 3685(一)nodeName 属性含有某个节点的名称。 元素节 ... -
javascript正则表达式总结
2012-03-16 13:53 1438正则表达式中特殊字符的含义 1、^ ^匹配输入字符串 ... -
javascript常用知识点总结(不断完善)
2011-07-04 17:15 1134一、函数中调用函数的实现 /** * 以下为 ... -
js对象的克隆
2011-06-14 15:02 2061由于js是采用引用传值的,故修改任何一个对象,其关 ... -
javascript中静态方法、实例方法、内部方法和原型的一点见解
2011-06-11 15:54 85511、静态方法的定义 var BaseClass = f ... -
javascript contains和compareDocumentPosition 方法来确定是否HTML节点
2011-03-30 17:41 14521、DOMElement.contains(DOMNode) ... -
事件mouseenter和事件mouseleave
2011-03-14 14:52 1785为了鼠标操作起来方便,IE实现了mouseenter 和m ... -
table列表中结合ctrl,shift实现多行的选择
2009-06-12 15:16 4298以下是简单的实现了tabl ... -
JavaScript中Array(数组)的属性和方法
2009-06-03 17:13 1368数组有四种定义的方式 ... -
表格自动换行
2008-12-02 11:06 3003有时表格中显示的内容不会根据长度的加长而自动换行,显示的效果很 ... -
让表格有滚动条的实现
2008-12-02 10:23 5593主要是用div样式来控制 例如 <html> ... -
利用javascript验证输入框中的值是否为日期格式
2008-09-02 15:45 127521、判断是否为年月日时间格式 <script> ... -
web一些值得珍藏的脚本代码
2008-08-01 09:50 12821. oncontextmenu="window.e ... -
div垂直和水平居中
2008-06-29 16:34 1704<div id="div_1" st ... -
JS创建日历控件
2008-06-29 16:32 1791// JavaScript Document /******* ... -
JS获取系统当前日期和时间
2008-06-29 16:31 6698<!DOCTYPE HTML PUBLIC " ...
相关推荐
软件基于Chromium内核, 它采用多线程框架设计,极大的优化了浏览器的内存占用,采用的多重加速机制,更大幅提高了网页的加载速度,并高度集成了115.com的多种重量级网络服务:聚合搜索、115网络U盘、在线收藏夹、...
云同步 - 收藏、选项设置、智能填表等账户数据瞬间同步,实现与Windows, Android, iOS平台设备上的无缝连接 超级拖拽 页面中拖拽链接可以在新标签内打开网页 拖拽图片可在新标签内查看图片或直接保存到桌面 拖拽...
Google搜索数据库的安全积累与沙盒机制的应用,保证了您在浏览时能杜绝99%的恶意软件侵入的机会! 安全、精简、快速、绿色,随时拷贝带走 Google服务器同步数据保存,一键恢复 快速与兼容模式随时切换,...
但是浏览器有addEventListener和attachEvent方法可供调用,从而模拟出类似于C#中的事件委托的事件触发机制! 代码如下: /* * 功能:事件处理 * Author:LQB * 时间:2009-1-4 * #include JCore.js */ var JEvents = ...
13.1.1 消息与事件响应 13.1.2 浏览器的事件驱动机制 13.2 基本事件处理 13.2.1 事件和事件类型 13.2.2 事件的绑定 13.2.3 直接调用事件处理函数 13.2.4 事件处理函数的返回值 13.2.5...
用采用RMI、CORBA或者自定义TCP/IP信息的applet来实现。这些技术往往由于复杂而产生诸多不利之处:技术难以实现、存在防火墙限制(因为需要打开非HTTP的通讯端口)、需要额外的server开发和维护。并且除了刷新整个...
2)本插件是基于同一台电脑上的FLASH之间能进行LocalConnection以及FLASH与JS能相互调用的原理而设计,将客户端不同域页面间Javascript相互调用转化为了FLASH之间的"本地命令发送". 3)本插件在不同域页面间Javascript...
浏览器支持度移动端主流浏览器(Android2.3 , iOS4.0 )PC端主流浏览器(Chrome, Safari, Firefox, IE8 )功能列表自定义元素Scoped CSS模板双向绑定监听属性事件模型方法切片Behaviors复用机制 标签:NovaJS
ToolBar工具栏控件的使用 动态建立主菜单选项 窗口界面的动态分隔条...自定义系统的About项 修改系统级菜单 实现透明窗体效果 爆破特技窗体 只允许建立一次子窗体的MDI程序 从外部DLL中调用子窗口...
第2章 JavaScript浏览器对象模型与事件处理 2.1 浏览器对象模型 2.1.1 文档对象 2.1.2 表单及其元素对象 2.1.3 浏览器信息对象 2.1.4 窗口对象 2.1.5 网址对象 2.1.6 历史记录对象 2.2 基本事件处理 2.3 2...
第2章 JavaScript浏览器对象模型与事件处理 2.1 浏览器对象模型 2.1.1 文档对象 2.1.2 表单及其元素对象 2.1.3 浏览器信息对象 2.1.4 窗口对象 2.1.5 网址对象 2.1.6 历史记录对象 2.2 基本事件处理 2.3 2...
5.2 事件和数据回发机制的实现 148 5.2.1 客户端回传事件接口ipostbackeventhandler 148 5.2.2 客户端回发/回调揭密 150 5.2.3 回传数据处理接口ipostbackdatahandler 153 5.2.4 正确处理继承基类中控件的事件 ...
灵活定义角色权限,全面面向集团应用5、内置工作流系统,通过傲视同群的可视化“智能表单设计”、灵活的图形化自定义流程,实现各项业务流程的管理,文件流转及审批6、完善灵活的菜单自定义机制,方便挂接外部的B/S...
3.10.3 功能实现 3.10.4 代码分析 3.11 本章小结 第4章 jquery中的事件与应用 4.1 事件机制 4.2 页面载入事件 4.2.1 ready()方法的工作原理 4.2.2 ready()方法的几种相同写法 4.3 绑定事件 ...
5.2 事件和数据回发机制的实现 148 5.2.1 客户端回传事件接口ipostbackeventhandler 148 5.2.2 客户端回发/回调揭密 150 5.2.3 回传数据处理接口ipostbackdatahandler 153 5.2.4 正确处理继承基类中控件的事件 ...
5.2 事件和数据回发机制的实现 148 5.2.1 客户端回传事件接口ipostbackeventhandler 148 5.2.2 客户端回发/回调揭密 150 5.2.3 回传数据处理接口ipostbackdatahandler 153 5.2.4 正确处理继承基类中控件的事件 ...
27.2.1 实现与浏览器通信的类 27.2.2 实现Web服务器的类 27.2.3 浏览器所请求的页面 27.3 知识点扩展——HTTP协议知识 27.3.1 HTTP协议原理 27.3.2 实现HTTP协议服务器的原理 27.4 小结 28.1 QQ聊天工具原理 28.1.1 ...
第二十一节:jQuery速成- 页面的载入事件与事件处理 第二十二节:jQuery速成- 鼠标事件与交互 第二十三节:jQuery速成- 焦点事件 第二十四节:jQuery速成- 键盘事件 第二十五节:jQuery速成- 其他事件 第六章:效果...