1. 程式人生 > >事件模型及事件代理/委託

事件模型及事件代理/委託

一、事件:

我們都知道在JS中,事件分三個階段:捕獲、目標、冒泡。

  • 捕獲:由外向內,由不具體到最具體,由document到元素
  • 目標:就是事件觸發的元素
  • 冒泡:由內向外,由最具體到最不具體,由元素到document

事件過程

二、事件處理程式:

1.DOM0級事件處理程式:

即直接在dom物件上註冊時間名稱,就是DOM0級寫法,DOM0事件模型,所以的瀏覽器都支援。
先取元素,再以物件屬性的形式新增事件,遵循覆蓋的原則,後面繫結的事件會覆蓋之前繫結的。

1)在HTML上新增
 缺點:高耦合,修改不方便,html與js聯絡太緊密
<button type="button"
onclick="dele()" id="btn">
delete</button> <script> function dele(){ alert(this);//window } </script>

這樣註冊的事件,相當於動態呼叫函式(有點eval的意思),因此不會傳入event物件,同時,this指向的是window,不再是觸發事件的dom物件,當然如果呼叫時傳入this則指代呼叫物件

<button type="button" onclick="dele(this)" id="btn">delete</button
>
<script> function dele(){ alert(this);//button } </script>
2)獲取元素新增
var btn = document.getELementById("btn");
btn.onclick = function(){//會被後面的繫結覆蓋
    alert("ok")
}
btn.onclick = function(){//實際會輸出'btn'
    alert(this.id)
}

因為事件就是在id為btn的dom節點上註冊的,事件觸發時,this就代表這個dom節點,可以理解為事件是被這個dom節點呼叫的

3)解綁DOM0級事件

原理就是最後註冊的事件要覆蓋之前的,最後一次註冊事件設定成null,也就解除了事件繫結。

btn.onclick = null;

2.DOM2級事件處理程式:

與DOM0級相比,DOM2級有兩大優點:
1. 可以給一個元素新增多個事件處理程式,會按順序執行,也可以新增多個事件
2. DOM2新增了捕獲和冒泡的概念,使得我們可以進行事件的代理委託,為動態生成的元素繫結事件

DOM2事件通過addEventListener和removeEventListener管理,分別用於繫結事件和解除繫結
1)繫結事件:addEventListener

有三個引數:
“事件名稱”: -string 事件名不用寫on
“事件回撥”: -function 預設傳入一個event引數
“捕獲/冒泡”:-boolean false為冒泡,true為捕獲
這裡必須要再祭出非常重要的事件過程圖了:
這裡寫圖片描述

var div = document.getElementById("div");
//冒泡事件
div.addEventListener("click", function(e){
  alert("ok");
}, false);
//捕獲事件
div.addEventListener("click", function(e){
  alert("ok1");
}, true);
2)解除繫結:removeEventListener

解除繫結同樣有三個引數:
“事件名稱”: -string 解除的事件名稱
“事件回撥”: -function 解除的回撥函式,必須和註冊時的一致,要想註冊過的事件能夠被解除,必須將回調函式儲存起來,否則無法解除。
“捕獲/冒泡”:-boolean 必須和註冊事件時的型別一致

var div= document.getElementById("div");
//將回調儲存在變數中
var fn = function(e){
  alert("ok");
};
//繫結
div.addEventListener("click", fn, false);

//解除
div.removeEventListener("click", fn, false);

3.IE事件處理程式:

DOM2級繫結事件確實給我們帶來了許多的便利,但是IE總是不能讓我們愉快的玩耍,對於反人類的低版本IE(IE8及其以下版本瀏覽器),addEventListener和removeEventListene是無法使用的,必須使用IE的方法:attachEvent和detachEvent
1)繫結事件:attachEvent

有兩個引數:
“事件名稱”: -string 事件名必須寫on
“事件回撥”: -function 預設傳入一個event引數

var div = document.getElementById("div");
div.attachEvent("onclick", function(e){
  alert("ok");
});
2)解除繫結:removeEventListener

也是有兩個引數:
“事件名稱”: -string 事件名必須寫on
“事件回撥”: -function 解除的回撥函式,必須和註冊時的一致,要想註冊過的事件能夠被解除,必須將回調函式儲存起來,否則無法解除。

var div= document.getElementById("div");
//將回調儲存在變數中
var fn = function(e){
  alert("ok");
};
//繫結
div.attachEvent("onclick", fn);

//解除
div.detachEvent("onclick", fn);

4.跨瀏覽器的事件處理程式:

為了瀏覽器的相容,我們使用能力檢測實現在各瀏覽器中使用事件繫結和解除事件繫結:

var eventUtil = {
    //新增控制代碼
    addHandler:function(ele,type,handler){
        if(ele.addEndEventListener){
            ele.addEndEventListener(type,handler,false);
        }else if(ele.attachEvent){
            ele.attachEvent('on'+type,handler);
        }else{
            ele['on'+type] = handler;
        }
    },
    //刪除控制代碼
    removeHandler:function(ele,type,handler){
        if(ele.removeEndEventListener){
            ele.removeEndEventListener(type,handler,false);
        }else if(ele.detachEvent){
            ele.detachEvent('on'+type,handler);
        }else{
            ele['on'+type] = null;
        }
    }
}
//呼叫
var btn = document.getElementById('btn');
var clickHandler = function(){
    alert(123)
}
eventUtil.addHandler(btn,'click',clickHandler);//繫結事件
eventUtil.removeHandler(btn,'click',clickHandler);//解除繫結

三、事件物件

Event 物件代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、滑鼠的位置、滑鼠按鈕的狀態。

1.DOM中的事件物件(event)

1)type 事件型別
2)target 事件目標
3)stopPropagation() 阻止事件冒泡
4)preventDefault() 取消預設行為

2.IE中的事件物件(event||window.event)

在低版本IE(IE8-)中事件物件為window.event,所以取得事件物件的相容寫法為

target = target || window.target;

1)type 事件型別
2)srcElement 事件目標
相容寫法:

    var ele = event.target||event.srcElement;

3)cancleBubble - boolean 阻止事件冒泡屬性 true阻止;false不阻止;
4)returnValue -boolean 取消預設行為屬性 true不取消;false取消;