事件模型的解释

原始事件模型

在原始事件模型中(也有说DOM0级),事件发生后没有传播的概念,没有事件流。事件发生,马上处理,完事,就这么简单。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:

  • HTML代码中指定属性值:
<input type=”button” onclick=”func1()” />
  • 在js代码中指定属性值:
document.getElementsByTagName(‘input’)[0].onclick = func1

优点:所有浏览器都兼容

缺点:

  • 逻辑与显示没有分离;
  • 相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的,如:a.onclick = func1; a.onclick = func2;将只会执行func2中的内容。
  • 无法通过事件的冒泡、委托等机制(后面系列会讲到)完成更多事情。

DOM2事件模型

此模型是W3C制定的标准模型,既然是标准,那大家都得按这个来,我们现在使用的现代浏览器(指IE6~8除外的浏览器)都已经遵循这个规范。W3C制定的事件模型中,一次事件的发生包含三个过程:

(1)capturing phase:事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。

(2)target phase:事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.

(3)bubbling phase:事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。

这里写图片描述

所有的事件类型都会经历captruing phase但是只有部分事件会经历bubbling phase阶段,例如submit事件就不会被冒泡。

<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
    <div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>

假设我们点击了ID为inner的div,那么此时的事件流程就是,首先执行捕获阶段:document-html-body-div(outer)。然后执行冒泡阶段:div(inner)-div(outer)-body-html-document

DOM2级的注册事件和解除事件

  在DOM2级中使用addEventListener和removeEventListener来注册和解除事件(IE8及之前版本不支持)。这种函数较之之前的方法好处是一个dom对象可以注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。
  

  • addEventListener(‘事件名称’,’事件回调’,’捕获/冒泡’)。

示例如下:

<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
    <div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>
<script>
    var click = document.getElementById('inner');
    click.addEventListener('click',function(){
        alert('click one');
    },false);
    click.addEventListener('click',function(){
        alert('click two');
    },false);
</script>

首先我们要知道addEventListenr的第一个参数是事件名称,与DOM0级不同的是没有”on“,另外第三个参数代表捕获还是冒泡,true代表捕获事件,false代表冒泡事件。

而在这段代码中,我们为inner的div注册了两个click事件函数,结果是浏览器会依次执行这两个函数。
  
我们在开发的时候需要兼顾IE与非IE浏览器,所以注册一个监听器应该这样写:

var a = document.getElementById('a');
if(a.attachEvent){
    a.attachEvent('onclick',func);
}
else{
    a.addEventListener('click',func,false);
}

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

停止事件冒泡

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

  • 在IE下,通过设置event对象的cancelBubble为true即可。
function someHandle() {
   window.event.cancelBubble = true;
 }
  • DOM标准通过调用event对象的stopPropagation()方法即可。
function someHandle(event) {
   event.stopPropagation();
 }
  • 因此,跨浏览器的停止事件传递的方法是:
function someHandle(event) {
   event = event || window.event;
   if(event.stopPropagation){
     event.stopPropagation();
   }else {
     event.cancelBubble = true;
   }
 }

阻止事件的默认行为

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

  • 在IE下,通过设置event对象的returnValue为false即可。
function someHandle() {
   window.event.returnValue = false;
 }
  • DOM标准通过调用event对象的preventDefault()方法即可。
function someHandle(event) {
   event.preventDefault();
 }
  • 因此,跨浏览器的取消事件传递后的默认处理方法是:
function someHandle(event) {
   event = event || window.event;
   if(event.preventDefault){
     event.preventDefault();
   }else{
     event.returnValue = false;
   }
 }

总结

  • 完整的事件处理兼容性函数
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;
     }
 };

详情推荐网站:http://blog.csdn.net/chenmoquan/article/details/10162477

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值