zoukankan      html  css  js  c++  java
  • 事件机制(事件冒泡与事件捕获)

    <div id="outer">
        <p id="inner">Click me!</p>
    </div>
    

    事件冒泡

    微软提出了名为事件冒泡(event bubbling)的事件流。时间冒泡就是指事件会从最内层的元素开始发生,一直向上传播,直到document对象。

    因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document

    事件捕获

    网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。

    上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p

    Netscape Navigator不会将页面上的很多元素暴漏给事件

    在DOM事件流中,“DOM2级事件”中规定的事件流同时支持了事件捕获阶段事件冒泡阶段

    穿插一个小片段,解释一下这里的dom2级事件。

    使用事件处理程序有三种方式:

    1、HTML事件处理程序

    如:<div id="outer">
        <p id="inner" onclick="alert("我是html事件处理程序");">Click me!</p>
    </div>


    2、DOM0级事件处理程序
    如:<div id="outer">
        <p id="inner">Click me!</p>
    </div>
    <script type="text/javascript">
    var pBtn=document.get
    ElementById("inner");

    pBtn.onclick=function(){
    }

    </script>

    3、DOM2级事件

      就是用addEventListener()等类型的,在事件处理上IE和DOM也是有区别的,

      IE中绑定事件和解绑为attachEvent(),detachEvent(),

      DOM中的为addEventListener(),removeEventListener()

      那么如何兼容此问题呢?如下代码,通过if..else类型判断

     <body>
          <div id="box">
             <input type="button" value="按钮" id="btn" onclick="showMes()">
             <input type="button" value="按钮2" id="btn2">
             <input type="button" value="按钮3" id="btn3">
             <a href="event.html" id="go">跳转</a>
          </div>
       </body>
    html
    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;
              },
              getType:function(event){
                return event.type;
              },
              getElement: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;
               }
             }
      }
    js
    window.onload=function(){
      var go=document.getElementById('go'),
          box=document.getElementById('box');
    
      eventUtil.addHandler(box,'click',function(){
          alert('我是整个父盒子');
      });
    
      eventUtil.addHandler(go,'click',function(e){
          //e=eventUtil.getEvent(e);
          e=e || window.event;
          alert(eventUtil.getElement(e).nodeName);
          eventUtil.preventDefault(e);
          eventUtil.stopPropagation(e);
      });
    
    }
    js

    应用例子:

    <ul id="color-list">
        <li>red</li>
        <li>yellow</li>
        <li>blue</li>
        <li>green</li>
        <li>black</li>
        <li>white</li>
    </ul>
    

    如果点击页面中的li元素,然后输出li当中的颜色,我们通常会这样写:

    (function(){
        var color_list = document.getElementById('color-list');
        var colors = color_list.getElementsByTagName('li');
        for(var i=0;i<colors.length;i++){                          colors[i].addEventListener('click',showColor,false);
        };
        function showColor(e){
            var x = e.target;
            alert("The color is " + x.innerHTML);
        };
    })();

    这样的代码再正常不过了,但是,如果页面上有几百个元素需要绑定(假设),那么务必就要绑定几百次啦。
    这样问题就出现了:

    第一:大量的事件绑定,性能消耗,而且还需要解绑(IE会泄漏)
    第二:绑定的元素必须要存在
    第三: 后期生成HTML会没有事件绑定,需要重新绑定
    第四: 语法过于繁杂

    在实际的开发当中,利用事件流的特性,我们可以使用一种叫做事件代理的方法。

    利用事件流的特性,我们只绑定一个事件处理函数也可以完成:

    (function(){
        var color_list = document.getElementById('color-list');
        color_list.addEventListener('click',showColor,false);
        function showColor(e){
            var x = e.target;
            if(x.nodeName.toLowerCase() === 'li'){
                alert('The color is ' + x.innerHTML);
            }
        }
    })();
    

    使用事件代理的好处不仅在于将多个事件处理函数减为一个,而且对于不同的元素可以有不同的处理方法。假如上述列表元素当中添加了其他的元素(如:a、span等),我们不必再一次循环给每一个元素绑定事件,直接修改事件代理的事件处理函数即可。

    关于事件对象

    在IE中事件对象是windows的一个属性event

    oDiv.onclick=function(){

      var oEvent=window.event;

    }

    DOM标准则说,event对象必须作为唯一参数传给事件处理函数,

    oDiv.onclick=function(){

      var oEvent=window.arguments【0】;

    }

    或者

    oDiv.onclick=function(oEvent){

    }

    可用event.type获取事件对象的类型

    event.target获取事件对象的目标

    event.stoppropagation()阻止冒泡

    在Jquery中如何用呢?

    具体来说,事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)
    

    委托这么好的特性 jQuery 当然不会放过,所以就衍生出  .bind()、.live() .on()和.delegate(),jQuery 的事件绑定有多个方法可以调用,以 click 事件来举例:

    click方法
    bind方法
    delegate方法
    on方法
    

    这里要清楚的认识:不管你用的是(click / bind / delegate)之中哪个方法,最终都是 jQuery 底层都是调用 on 方法来完成最终的事件绑定。因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不如直接都采用 on 方法来的痛快和直接。

    所以在新版的 API 中都这么写到:

    .on()方法事件处理程序到当前选定的 jQuery 对象中的元素。在jQuery 1.7中,.on()方法提供绑定事件处理的所有功能、效果不言而喻了,除了性能的差异,通过委托的事件还能很友好的支持动态绑定,只要 on 的delegate 象是 HTML 页面原有的元素,由于是事件的触发是通过Javascript的事件冒泡机制来监测,所以对于所有子元素(包括后期通过JS生成的元素)所有的事件监测均能有效,且由于不用对多个元素进行事件绑定,能够有效的节省内存的损耗。
  • 相关阅读:
    python的json模块介绍
    采用boosting思想开发一个解决二分类样本不平衡的多估计器模型
    kappa系数
    android服务
    Android Studio 无法预览布局问题:com/android/util/PropertiesMap
    pitch yaw roll是什么
    keil5破解
    Eclipse/jre/jdk/jvm
    传感器
    Java静态代码块
  • 原文地址:https://www.cnblogs.com/lpshan/p/4591053.html
Copyright © 2011-2022 走看看