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

什麼是事件委託/事件代理?
html

js高級程序:事件委託就是利用事件冒泡,只指定一個事件處理程序,就能夠管理某一類型的全部事件。瀏覽器

通俗點說就是利用事件的冒泡傳播機制(觸發當前元素的某一個行爲,它父級全部元素相關行爲都會被觸發),若是一個容器中有不少元素都要綁定點擊事件,沒有必有一個一個的綁定了,只須要給最外層的容器綁定一個點擊事件便可,在這個方法執行的時候,經過事件源的區分來進行不一樣的操做。性能優化

經常使用案例:bash

有三個同事預計會在週一收到快遞。爲簽收快遞,有兩種辦法:一是三我的在公司門口等快遞;二是委託給前臺MM代爲簽收。現實當中,咱們大都採用委託的方案(公司也不會容忍那麼多員工站在門口就爲了等快遞)。前臺MM收到快遞後,她會判斷收件人是誰,而後按照收件人的要求籤收,甚至代爲付款。這種方案還有一個優點,那就是即便公司裏來了新員工(無論多少),前臺MM也會在收到寄給新員工的快遞後覈實並代爲簽收。dom

這裏其實還有2層意思的:函數

第一,如今委託前臺的同事是能夠代爲簽收的,即程序中的現有的dom節點是有事件的;性能

第二,新員工也是能夠被前臺MM代爲簽收的,即程序中新添加的dom節點也是有事件的。優化

爲何要用事件委託:

通常來講,dom須要有事件處理程序,咱們都會直接給它設事件處理程序就行了,那若是是不少的dom須要添加事件處理呢?好比咱們有100個li,每一個li都有相同的click點擊事件,可能咱們會用for循環的方法,來遍歷全部的li,而後給它們添加事件,那這麼作會存在什麼影響呢?ui

在JavaScript中,添加到頁面上的事件處理程序數量將直接關係到頁面的總體運行性能,由於須要不斷的與dom節點進行交互,訪問dom的次數越多,引發瀏覽器重繪與重排的次數也就越多,就會延長整個頁面的交互就緒時間,這就是爲何性能優化的主要思想之一就是減小DOM操做的緣由;若是要用事件委託,就會將全部的操做放到js程序裏面,與dom的操做就只須要交互一次,這樣就能大大的減小與dom的交互次數,提升性能;this

每一個函數都是一個對象,是對象就會佔用內存,對象越多,內存佔用率就越大,天然性能就越差了(內存不夠用,是硬傷,哈哈),好比上面的100個li,就要佔用100個內存空間,若是是1000個,10000個呢,那隻能說呵呵了,若是用事件委託,那麼咱們就能夠只對它的父級(若是隻有一個父級)這一個對象進行操做,這樣咱們就須要一個內存空間就夠了,是否是省了不少,天然性能就會更好。

1、事件:

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

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

事件過程

2、事件處理程序:

1.DOM0級事件處理程序:

即直接在dom對象上註冊時間名稱,就是DOM0級寫法,DOM0事件模型,因此的瀏覽器都支持。
先取元素,再以對象屬性的形式添加事件,遵循覆蓋的原則,後面綁定的事件會覆蓋以前綁定的。

1)在HTML上添加
缺點:高耦合,修改不方便,html與js聯繫太緊密
12複製代碼
<button type="button" onclick="dele()" id="btn">delete</button>
<script>
    function dele(){
        alert(this);//window
    }
</script>123456複製代碼

這樣註冊的事件,至關於動態調用函數(有點eval的意思),所以不會傳入event對象,同時,this指向的是window,再也不是觸發事件的dom對象,固然若是調用時傳入this則指代調用對象

<button type="button" onclick="dele(this)" id="btn">delete</button>
<script>
    function dele(){
        alert(this);//button
    }
</script>
1234567複製代碼
2)獲取元素添加
var btn = document.getELementById("btn");
btn.onclick = function(){//會被後面的綁定覆蓋
    alert("ok")
}
btn.onclick = function(){//實際會輸出'btn'
    alert(this.id)
}1234567複製代碼

由於事件就是在id爲btn的dom節點上註冊的,事件觸發時,this就表明這個dom節點,能夠理解爲事件是被這個dom節點調用的

3)解綁DOM0級事件

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

btn.onclick = null;1複製代碼

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);123456789複製代碼
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);12345678910複製代碼

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");
});1234複製代碼
2)解除綁定:removeEventListener

也是有兩個參數:
「事件名稱」: -string 事件名必須寫on
「事件回調」: -function 解除的回調函數,必須和註冊時的一致,要想註冊過的事件可以被解除,必須將回調函數保存起來,不然沒法解除。

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

//解除
div.detachEvent("onclick", fn);12345678910複製代碼

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);//解除綁定1234567891011121314151617181920212223242526272829複製代碼

3、事件對象

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複製代碼

1)type 事件類型
2)srcElement 事件目標
兼容寫法:

var ele = event.target||event.srcElement;1複製代碼

3)cancleBubble - boolean 阻止事件冒泡屬性 true阻止;false不阻止; 4)returnValue -boolean 取消默認行爲屬性 true不取消;false取消;

相關文章
相關標籤/搜索