DOM事件流

一直以來,在DOM中添加事件老是使用三種方法,html

第一種使用HTML中的事件處理程序例如:面試

<button onclick=' $$ '></button>

第二種:使用在JavaScript中添加事件處理程序:瀏覽器

var s =document.getElementById('id');
s.oncilck=function(){}

第三種使用 addEventListener 方法註冊事件處理程序:函數

document.getElementById('id').addEventListener('click',function(){})//注意是click

一直是這樣用的,卻沒有理解使用的弊端和注意的問題,如今總結一下這三者DOM事件處理方法的優劣。this

1、事件流

事件流有兩種,事件冒泡事件捕獲,它表示當用戶觸發了某個頁面元素的動做,應該由怎樣的方式向「觀察者」傳遞;就像是身爲校長的你,學生髮生了一塊兒鬥毆事件,你是經過挨個年級-班級去找到滋事者(事件捕獲);仍是經過一個學生主動告訴你事情發生的通過(事件冒泡);某種程度上,中國寫信的地址方式和美國的寫信的地址,有些相似冒泡和捕獲的過程。spa

一、事件冒泡

假如一篇文檔的結構:設計

<html>
<head> </head>
<body>
<div></div>
</body>
</html>

當點擊div元素 ,觸發了click事件,那麼冒泡傳遞的方式是這樣的,code

二、事件捕獲

天然是反方向的:htm

三、DOM事件流

不少面試會有問到這個問題,實際上DOM事件流是DOM2級事件中規定的,它包括,事件捕獲階段,目標發生階段,和事件冒泡階段。對象

 

值得注意的是,div元素不會在捕獲階段接受事件,也就是捕獲的過程到body後就中止了,接下來是目標階段;在事件處理中屬於冒泡階段的一部分,

 DOM2中規定捕獲階段不會設計目標事件,可是高版本瀏覽器沒有遵循規定;所以就有兩個機會在目標對象中操做事件。

 2、事件處理程序

事件的名稱 click ;load;mouseover;事件處理程序以‘on’開頭;所以click事件的事件處理程序就是onclickload事件的事件處理程序就是onload

一、HTML事件處理程序

 HTML事件處理程序能夠直接在事件處理程序中,添加執行的函數,也能夠進行調用其餘地方定義的腳本;

<button oncilck="alert('hello world!')"></button>//執行代碼直接添加到事件中
<script>
function hello(){
alert('hello,world!')
}
</script>

<button onclick='hello()'></button>//調用其餘腳本

HTML事件處理程序優勢

  • 會建立一個封裝着元素屬性值的函數,這個函數中有一個局部變量event,也就是事件對象。
<input type='button' value='click me' onclick='alert(this.value)'>//click me this值指向發生事件的目標元素;
<input type='button' value='click' onclick='alert(event.type)'>//click 經過event對象能夠訪問事件對象;

HTML事件處理程序缺點

  • 失去響應。若是定義的腳本在觸發事件元素的後面進行定義的,極可能在沒有加載腳本以前;用戶點擊了元素,會失去響應;(JavaScript引擎是逐行讀取代碼的)
  • HTML與JavaScript高度耦合,缺少可維護性和增長維護成本。

二、DOM 0 級事件處理程序

JavaScript中常見的處理事件的方式,經過將函數賦值給一個事件處理程序屬性;簡單,並且跨瀏覽器;

var but=document.getElementById('id');
but.onclick=function(){
    alert(this.value)
}

這種方式的事件 處理程序在事件流的冒泡階段被處理。

but.onclick=null;//阻止事件處理的方式,設置null;

三、DOM 2級事件處理程序

經過addEventListener()    removeEventListener(),方法註冊和刪除事件處理程序,接受3個參數,事件名,處理函數,布爾值;

var but=document.getElementById('id');
but.addEventListener('click',function(){
    alert('this.value');
},false);

布爾值true表示在事件流捕獲階段觸發調用,布爾值false 表示在冒泡階段調用事件處理程序。

注意:

  • 第二個參數是事件名,不是事件處理函數名, ‘click’而不是‘onclick’,與前兩個方式不一樣。
  • 能夠添加多個事件處理程序;處理的順序按照註冊的順序執行。
var but=document.getElementById('id');
but.addEventListener(
'click',function(){ alert('this.value'); },false);
but.addEventListener(
'click',function(){ alert('hello world'); },false);
  • 匿名函數沒法經過removeEventListener()方法移除事件處理程序,由於兩次的匿名函數不是同一個函數,
var but=document.getElementById('id');

but.addEventListener('click',function(){
    alert('hello world');
},false);

but.removeEventListener('click',function(){
    alert('hello world');
},false);//無效,由於第二個參數是徹底不一樣的匿名函數,只是定義相同;
var but=document.getElementById('id');

function hello(){
    alert('hello world')
}

but.addEventListener('click',hello,false);
but.removeEventListener('click',hello,false)//有效,使用相同函數

四、IE事件處理程序

IE使用attachEvent()  detachEvent()兩個方法添加事件處理,這兩個方法分別接受兩個參數,事件處理名稱,事件處理函數;因爲IE8更早版本只支持事件冒泡,所以經過attachEvent() 添加的時間處理程序會被添加到冒泡階段。
注意

  • attachEvent() 第一個參數是「onclick」 而不是「click」;
  • attachEvent() 也能夠添加多個事件,不過執行的順序徹底相反;
  • 能夠經過 detachEvent() 方法移除事件,和removeEventListener() 相似;不能移除匿名函數。
var but=document.getElementById('id');
function hello(){
    alert('hello world')
}

but.attachEvent('onclick',hello);
but.attachEvent('onclick',function(){
    alert('this.id')
})//先 彈出id ,後彈出 hello world
相關文章
相關標籤/搜索