JavaScirpt事件处理

1、事件流

事件流,描述的是页面中接受事件的顺序,不过,IE的事件流是事件冒泡流,而Netscape Communicator的事件流是事件捕获型。标准同时支持两种事件模型,即捕获型事件与冒泡型事件,可是,捕获型事件先发生。javascript

两种事件流都会触发DOM中的全部对象,从document对象开始,也在document对象结束(大部分兼容标准的浏览器会继续将事件是捕捉/冒泡延续到window对象)JavaScript与HTML之间的交,经过事件实现。经常使用观察员模式,使用侦听器来预约事件,以便事件发生时执行相应的代码。html

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

2、事件句柄和事件监听器

事件句柄与事件监听器的最大不一样之处是使用事件句柄时一次只能插接一个事件句柄,但对于事件监听器,一次能够插接多个。如今大多数浏览器都内置了一些更高级的事件处理方式,即,事件监听器,这种处理方式就不受一个元素只能绑定一个事件句柄的限制。浏览器

获取事件的目标

HTML以下:dom

body id="myBody">
    <button id="myButton">click</button>
</body>

1. IE下的事件监听器:attachEvent接受两个参数。第一个参数是事件类型名,第二个参数eventListener是回调处理函数。

在IE中,每一个元素和window对象都有两个方法:attachEvent方法和detachEvent方法。函数

IE 事件对象使用 event 的 srcElement 属性获取事件目标。性能

var btn = document.getElementById("myButton");
btn.attachEvent("onclick", function(event) {
    alert(event.srcElement.id);    // myButton
});

2. DOM标准下的事件监听器:addEventListener

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

经过addEventListener方法添加的事件处理函数,必须使用removeEventListener方法才能删除,并且要求参数与添加事件处理函数时addEventListener方法的参数彻底一致(包括useCapture参数),不然将不能成功删除事件处理函数。设计

标准事件对象使用 event 的 target 属性获取事件目标:代理

var btn = document.getElementById('myButton');
btn.addEventListener("click", function(event) {
    alert(event.target.id);    // myButton
});

3、取消事件默认行为

html结构以下:

<div id="oDiv">
    <a id="oA" href="http://baidu.com">
        百度一下,你就知道。
    </a>
</div>

正常状况下,咱们点击a连接,会跳转到baidu.com,但当使用了e.preventDefault().

JS代码以下:

var a = document.getElementById("oA");

    //获取div
    var oDiv = document.getElementById('oDiv');

        //dom0级绑定事件方法
        a.onclick=function(e){
            e.preventDefault();
        }
   // 旧版本IE不支持捕获,通常使用冒泡。
        oDiv.addEventListener("click", function (e) {
            e.preventDefault();
        }, false);

4、禁止冒泡

1、正常状况下:

//关于阻止事件冒泡.ie678用attachEvent
    a.addEventListener("click", function (e) {
        alert(1);
    }, false);//冒泡


    oDiv.addEventListener("click", function (e) {
        alert(2)
    }, false);//冒泡

    oDiv.addEventListener("click", function (e) {
        alert(3);
    }, true);//捕获,捕获先发生

第3个参数设置为false时候为冒泡,先捕获,后冒泡。这里弹出顺序依次是:3,1,2

2、禁止冒泡时:用到stopPropagation

//关于阻止事件冒泡.ie678用attachEvent
    a.addEventListener("click", function (e) {
        e.stopPropagation();//阻止冒泡/捕获
        alert(1);
    }, false);//冒泡


    oDiv.addEventListener("click", function (e) {
        alert(2)
    }, false);//冒泡

    oDiv.addEventListener("click", function (e) {
        e.stopPropagation();
        alert(3);
    }, true);//捕获,捕获先发生

这时候顺序是:3,不会出现1,2。由于在第3个函数里用到了stopPropagation,并且捕获比冒泡事件先发生。因此只会出现3.

注意:e.cancelBubble = true对应取消冒泡;e.returnValue = true对应阻止默认行为

5、addEventListener与attachEvent区别

 1. 支持的浏览器

    addEventListener在支持DOM2的浏览器中使用,如FF, Chrome等

    attachEvent为IE所用

 2. 处理程序执行阶段

    addEventListener的第三个参数为true时,在捕获阶段执行,为false时,在冒泡阶段执行

    attachEvent的均在冒泡阶段执行

 3. 做用域

    addEventListener的做用域为元素做用域,this为element的引用

    addEvent的为全局做用域,this为window的引用

 4. 事件处理程序执行顺序

    addEventHander:执行顺序与添加顺序一致

    attachEvent:执行顺序与添加顺序相反

5. 针对的事件不一样

attachEvent中的事件带on 
 
    addEventListener中的事件不带on

6、冒泡的用处

例如:有一个10列、100行的HTML表格,假若有一次你须要让表格中的每个单元格在被点击的时候变成可编辑状态。

若是把事件处理器加到这1000个单元格会产生一个很大的性能问题,而且有可能致使内存泄露甚至是浏览器的崩溃。

相反地,使用事件代理的话,只须要把一个事件处理器添加到table元素上就能够了,这个函数能够把点击事件给截下来,而且判断出是哪一个单元格被点击了。

好比:有一个 table元素,ID是“report”,咱们为这个表格添加一个事件处理器以调用editCell函数。editCell函数须要判断出传到table 来的事件的目标元素。考虑到咱们要写的几个函数中都有可能用到这一功能,因此咱们把它单独放到一个名为getEventTarget的函数中:

function getEventTarget(e) {
  e = e || window.event;
  return e.target || e.srcElement;
}

e这个变量表示的是一个事件对象,咱们只须要写一点点跨浏览器的代码来返回目标元素,在IE里目标元素放在srcElemtn属性或event.toElement属性中,而在其它浏览器里则是target或event.relatedTarget属性。

接下来就是editCell函数了,这个函数调用到了 getEventTarget函数。一旦咱们获得了目标元素以后,剩下的事情就是看看它是不是咱们所须要的那个元素了。

function editCell(e) {
  var target = getEventTarget(e);
  if(target.tagName.toLowerCase() === 'td') {
    // DO SOMETHING WITH THE CELL
  }
}

经过事件冒泡,那些须要建立的以及驻留在内存中的事件处理器少了。这样咱们就提升了性能,并下降了崩溃的风险。

参考:《JavaScript高级程序设计》

相关文章
相关标签/搜索