1. 程式人生 > >js事件冒泡、事件繫結、事件監聽、事件委託

js事件冒泡、事件繫結、事件監聽、事件委託

點選連結

事件機制

事件繫結

首先要對 DOM 元素繫結事件處理函式。所謂事件處理函式,就是處理使用者操作的函式,不同的操作對應不同的名稱。

事件繫結的辦法:
1.直接在HTML元素繫結,在標籤後加onclick = function(){}等
2.在js指令碼中繫結,獲取元素後繫結事件
3.DOM繫結,新增事件監聽

 第一種無法刪除,不好維護
 第二種無法刪除,維護性一般
 第三種可以刪除,維護性一般

在DOM中直接繫結

可以在DOM元素上繫結onclick、onmouseover、onmouseout、onmousedown、onmouseup、ondblclick、onkeydown、onkeypress、onkeyup等。
<input type="button" value="click me" onclick="hello()">

<script>
   function hello(){
       alert("hello world");
}
</script>

js程式碼繫結事件

可以使js程式碼和HTML標籤分離,使文件結構清晰,便於開發管理

<input type = "button" value="click me" id="btn">

<script>
document.getElementById("btn").onclick = function
(){
alert("hello world!"); }
</script>

用事件監聽繫結事件

用 addEventListener() 或 attachEvent() 來繫結事件監聽函式。addEventListener()是標準的繫結事件監聽函式的方法,是W3C所支援的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支援該函式,但是IE8.0及其以下版本不支援該方法,使用addEventListener()繫結函式時,必須要處理瀏覽器相容問題

事件監聽

W3C定義了三個事件階段:捕獲階段、目標階段、冒泡階段

W3C規範:

語法:element.addEventListener(event,function,useCapture)

event : (必需)事件名,支援所有 DOM事件 。

function:(必需)指定要事件觸發時執行的函式。

useCapture:(可選)指定事件是否在捕獲或冒泡階段執行。true,捕獲。false,冒泡。預設false。

<input type="button" value="click me" id="btn1">

<script>
document.getElementById("btn1").addEventListener("click",hello);
function hello(){
    alert("hello world");
}
</script>
IE標準

語法:element。attachEvent(event,function)

event:(必需)事件型別。需加“on“,例如:onclick。

function:(必需)指定要事件觸發時執行的函式。

<input type="button" value="click me" id="btn2">

<script>
document.getElementById("btn2").attachEvent("onclick",hello);
function hello(){
    alert("hello world!");
}
</script>

事件監聽的優點

1.可以繫結多個事件

常規的事件繫結只能執行最後的繫結事件

<input type="button" value="click me" id="btn3">
<script>
var btn3 = document.getElementById("btn3");
btn3.onclick = function(){
    alert("hello 1"); //不執行
}
btn3.onclick = function(){
    alert("hello 2"); //執行
}
</script>

事件監聽可以繫結多個事件

<input type="button" value="click me" id="btn4">

<script>
var btn4 = document.getElementById("btn4");
btn4.addEventListener("click",hello1);
btn4.addEventListener("click",hello2);

function hello1(){
    alert("hello 1");
}
function hello2(){
    alert("hello 2");
}
</script>
2.可以解除相應的繫結
<input type="button" value="click me" id="btn5">

<script>
var btn5 = document.getElementById("btn5");
btn5.addEventListener("click",hello1);//執行了
btn5.addEventListener("click",hello2);//不執行
btn5.removeEventListener("click",hello2);

function hello1(){
    alert("hello 1");
}
function hello2(){
    alert("hello 2");
}
</script>

封裝事件監聽

<input type="button" value="click me" id="btn5">

//繫結監聽事件
function addEventHandler(target,type,fn){
    if(target.addEventListener){
        target.addEventListener(type,fn);
    }else{
        target.attachEvent("on"+type,fn);
    }
}

//移除監聽事件
function removeEventHandler(target,type,fn){
    if(target.removeEventListener){
        target.removeEventListener(type,fn);
    }else{
        target.detachEvent("on"+type,fn);
    }
}

//測試
var btn5 = document.getElementById("btn5");
addEventHandler(btn5,"click",hello1);//新增事件hello1
addEventHandler(btn5,"click",hello2);//新增事件hello2
removeEventHandler(btn5,"click",hello1);//移除事件hello1

事件委託(事件代理)

事件委託利用事件的冒泡原理來實現的,事件從最深的節點開始,然後逐步向上傳播事件,舉個例子:頁面上有這麼一個節點樹,div>ul>li>a;比如給最裡面的a加一個click點選事件,那麼這個事件就會一層一層的往外執行,執行順序a>li>ul>div,有這樣一個機制,那麼我們給最外面的div加點選事件,那麼裡面的ul,li,a做點選事件的時候,都會冒泡到最外層的div上,所以都會觸發,這就是事件委託,委託它們父級代為執行事件。

事件委託就 是事件目標自身不處理事件,而是把處理任務委託給其父元素或者祖先元素,甚至根元素(document),觸發執行效果。實際程式碼中會用到jQuery的live(),delegate()、bind()、on()等。

<input type="button" value="click me" id="btn6">

var btn6 = document.getElementById("btn6");
document.onclick = function(event){
    event = event || window.event;
    var target = event.target || event.srcElement;
    if(target == btn6){
        alert(btn5.value);
    }
}

事件委託優點

1、提高JavaScript效能。事件委託可以顯著的提高事件的處理速度,減少記憶體的佔用。
2、動態的新增DOM元素,不需要因為元素的改動而修改事件繫結。

事件捕獲與事件冒泡

參考連結

事件冒泡和事件捕獲是對同一件事情的不同看法。

如果瀏覽器採用的是事件冒泡,那麼觸發順序是C–>B–>A,由內而外,像氣泡一樣,從水底浮向水面;如果採用的是事件捕獲,那麼觸發順序是A–>B–>C,從上到下,像石頭一樣,從水面落入水底。

事件冒泡如圖:
事件冒泡
事件捕獲如圖:
事件捕獲

在IE8以及之前,IE只支援事件冒泡。IE9+/FF/Chrome這2種模型都支援,可以通過addEventListener((type, listener, useCapture)的useCapture來設定,useCapture=false代表著事件冒泡,useCapture=true代表著採用事件捕獲。

阻止事件冒泡