javascript 中的事件处理机制

   先看一段代码:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title></title>
    <script type="text/javascript" language="javascript" >
        function ClickButton() {
            alert("点击按钮");
        }

        function ClickDiv() {
            alert("点击Div");
        }
    </script>
</head>
<body>
<div οnclick="ClickDiv();" style="width:200px; height:300px; background-color:Red;">
<button id="Button1" οnclick="ClickButton();">测试</button>
</div>
</body>
</html>

如果点击测试按钮会出现什么样的效果?很多人都知道会先弹出“点击按钮”消息框,然后弹出"点击Div"消息框。为什么会是这样的效果呢,那我们就要了解一下javascript 的事件机制。

DOM事件流

DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程可称为DOM事件流。

事件顺序有两种类型:事件捕捉事件冒泡

冒泡型事件(Event Bubbling)

冒泡,顾名思义,事件像个水中的气泡一样一直往上冒,直到顶端。从DOM树型结构上理解,就是事件由叶子节点沿祖先结点一直向上传递直到根节点;从浏览器界面视图HTML元素排列层次上理解就是事件由具有从属关系的最确定的目标元素一直传递到最不确定的目标元素.冒泡技术.冒泡型事件的基本思想,事件按照从特定的事件目标开始到最不确定的事件目标.

捕获型事件(Event Capturing)

它与冒泡型刚好相反,由DOM树最顶层元素一直到最精确的元素,这个事件模型对于开发者来说有点费解,因为直观上的理解应该如同冒泡型,事件传递应该由最确定的元素,即事件产生元素开始。

w3c标准约定首先是捕获式传递事件,接着是冒泡式传递,所以,如果一个处理函数既注册了捕获型事件的监听,又注册冒泡型事件监听,那么在DOM事件模型中它就会被调用两次。以Netscape为代表的浏览器采用的w3c的标准,而以IE为代表的浏览器只支持冒泡式传递。

标准的事件转送模式

(1).在事件捕捉(Capturing)阶段,事件将沿着DOM树向下转送,目标节点的每一个祖先节点,直至目标节点。例如,若用户单击了一个超链接,则该单击事件将从document节点转送到html元素,body元素以及包含该链接的p元素。

在此过程中,浏览器都会检测针对该事件的捕捉事件监听器,并且运行这件事件监听器。

(2). 在目标(target)阶段,浏览器在查找到已经指定给目标事件的事件监听器之后,就会运行 该事件监听器。目标节点就是触发事件的DOM节点。例如,如果用户单击一个超链接,那么该链接就是目标节点(此时的目标节点实际上是超链接内的文本节点)。

(3).在冒泡(Bubbling)阶段,事件将沿着DOM树向上转送,再次逐个访问目标元素的祖先节点到document节点。该过程中的每一步。浏览器都将检测那些不是捕捉事件监听器的事件监听器,并执行它们。

并非所有的事件都会经过冒泡阶段的

       所有的事件都要经过捕捉阶段和目标阶段,但是有些事件会跳过冒泡阶段。例如,让元素获得输入焦点的focus事件以及失去输入焦点的blur事件就都不会冒泡。

事件监听器

     和上面的例子一样在HTML中直接给控件添加事件的方式是传统的事件绑定方式,现在大多数浏览器都内置了一些更高级的事件处理方式,这样就可以一次绑定多个事件

IE下的事件监听器:

给元素添加事件

element.attachEvent("onevent",eventListener);

移除先前元素注册的事件

elem.detachEvent("onevent",eventListener);


DOM标准下的事件监听器:

在支持W3C标准事件监听器的浏览器中,对每个支持事件的对象都可以使用addEventListener方法。该方法既支持注册冒泡型事件处理,又支持捕获型事件处理。所以与IE浏览器中注册元素事件监听器方式有所不同的。

 //标准语法 
 element.addEventListener('event', eventListener, useCapture);
//默认
element.addEventListener('event', eventListener, false);

addEventListener方法接受三个参数。第一个参数是事件类型名,值得注意的是,这里事件类型名称与IE的不同,事件类型名是没’on’开头的;第二个参数eventListener是回调处理函数(即监听器函数);第三个参数注明该处理回调函数是在事件传递过程中的捕获阶段被调用还是冒泡阶段被调用 ,通常此参数通常会设置为false(为false时是冒泡),那么,如果将其值设置为true,那就创建一个捕捉事件监听器。

移除已注册的事件监听器调用element的removeEventListener方法即可,参数相同。

//标准语法 
 element.removeEventListener('event', eventListener, useCapture);
//默认
 element.removeEventListener('event', eventListener, false);


跨浏览器的注册与移除元素事件监听器方案

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 1 var EventUtil = {
   //注册
   addHandler: function(element, type, handler){
     if (element.addEventListener){
       element.addEventListener(type, handler, false);
     } else if (element.attachEvent){
       element.attachEvent("on" + type, handler);
     } else {
       element["on" + type] = handler;
     }
   },
   //移除注册
   removeHandler: function(element, type, handler){
     if (element.removeEventListener){
             element.removeEventListener(type, handler, false);
     } else if (element.detachEvent){
             element.detachEvent("on" + type, handler);
     } else {
             element["on" + type] = null;
     }
   }             
  };


获取事件对象的跨浏览器方法

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->1 var EventUtil ={
   getEvent: function(event){
     return event ? event : window.event;
   },
   getTarget: function(event){
     return event.target || event.srcElement;
   }
 };


停止事件冒泡和阻止事件的默认行为

“停止事件冒泡“和”阻止浏览器的默认行为“,这两个概念非常重要,它们对复杂的应用程序处理非常有用。

1.停止事件冒泡

停止事件冒泡是指,停止冒泡型事件的进一步传递(取消事件传递,不只是停止IE和DOM标准共有的冒泡型事件,我们还可以停止支持DOM标准浏览器的捕捉型事件,用topPropagation()方法)。例如上图中的冒泡型事件传递中,在body处理停止事件传递后,位于上层的document的事件监听器就不再收到通知,不再被处理。

2.阻止事件的默认行为

停止事件的默认行为是指,通常浏览器在事件传递并处理完后会执行与该事件关联的默认动作(如果存在这样的动作)。例如,如果表单中input type 属性是 “submit”,点击后在事件传播完浏览器就自动提交表单。又例如,input 元素的 keydown 事件发生并处理后,浏览器默认会将用户键入的字符自动追加到 input 元素的值中。

在IE下,通过设置event对象的cancelBubble为true即可实现停止事件冒泡,通过设置event对象的returnValue为false即可阻止事件的默认行为
function someHandle() {
   window.event.cancelBubble = true;
 }
function someHandle() {
   window.event.returnValue = false;
}
DOM标准通过调用event对象的stopPropagation()方法即可即可实现停止事件冒泡,DOM标准通过调用event对象的preventDefault()方法即可阻止事件的默认行为
function someHandle(event) {
   event.stopPropagation();
 }
function someHandle(event) {
   event.preventDefault();
 }

因些,完整的事件处理兼容性函数是:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> 1 var EventUtil = {
   addHandler: function(element, type, handler){
     if (element.addEventListener){
       element.addEventListener(type, handler, false);
     } else if (element.attachEvent){
       element.attachEvent("on" + type, handler);
     } else {
       element["on" + type] = handler;
     }
   },
   removeHandler: function(element, type, handler){
     if (element.removeEventListener){
       element.removeEventListener(type, handler, false);
     } else if (element.detachEvent){
       element.detachEvent("on" + type, handler);
     } else {
       element["on" + type] = null;
     }
   },
   getEvent: function(event){
     return event ? event : window.event;
   },
   getTarget: function(event){
     return event.target || event.srcElement;
   },
   preventDefault: function(event){
     if (event.preventDefault){
       event.preventDefault();
     } else {
       event.returnValue = false;
     }
   },
   stopPropagation: function(event){
     if (event.stopPropagation){
       event.stopPropagation();
     } else {
       event.cancelBubble = true;
     }
 };
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值