JavaScript綁定事件的三種方式

@(javascript)[JavaScript事件綁定]javascript

JavaScript綁定事件的三種方式

  • 使用內聯
  • 使用.onclick的方式
  • 使用事件監聽addEventListener的方式

內聯

形式:html

<input type="button" value="按鈕" onclick="alert(1);">
複製代碼

這種方式就是在一個元素上面直接綁定了一個點擊onclick事件,此事件爲DOM 0級標準。同時,這個事件的優先級是最高的。java

使用對象.事件的形式

形式node

<input type="button" value="按鈕">

<script type="text/javascript"> var bt = document.getElementsBytagname("input")[0]; bt.onclick = function(){ alert(2) } </script>
複製代碼

使用這種形式也是能夠給一個DOM元素添加上一個事件。這個也是DOM 0級標準閉包

以上的弊端

以上兩種方式都是存在一個弊端的,就是一個元素只能添加一個事件。第一種就不用說了,寫在行內就一個屬性。至於第二種,有的網友可能會說我能夠再寫一個,好比:函數

<input type="button" value="按鈕">

<script type="text/javascript"> var bt = document.getElementsBytagname("input")[0]; bt.onclick = function(){ alert(2) } bt.onclick = function(){ alert(3) } </script>
複製代碼

寫是能夠這麼寫。那麼咱們先來看一看這個寫法的意思,這種寫法的本質就是在一個對象上添加一個屬性,就上面的例子,就是在bt這個對象上添加一個onclick屬性。那麼,若是在以後的代碼中也存在bt.onclcik,只會吧前面的給覆蓋了。因此這樣的寫法也只能添加一個事件。ui

那麼,問題來了。我要給一個元素(DOM對象)添加兩個甚至是多個事件,使用什麼呢?此時,就須要使用addEventListener的方式來添加事件。this

addEventListener

形式:spa

<input type="button" value="按鈕">

<script type="text/javascript"> var bt = document.getElementsBytagname("input")[0]; bt.addEventListener("click", function(){ alert(1) }) bt.addEventListener("click", function(){ alert(2) }) </script>
複製代碼

上面的方式就能夠給一個DOM對象綁定一個或者是多個事件。強烈推薦使用這一種綁定事件的方式。 使用addEventListener的方式還能夠擁有第三個參數。 如下是W3C官網的一個話 代理

三個參數:

  1. 事件類型,不須要添加上on
  2. 事件函數
  3. 是否捕獲(布爾值),默認是false,即不捕獲,那就是冒泡。

那麼捕獲和冒泡又是什麼呢? 這是三個盒子,相互嵌套的關係

<div id="a">
	a
	<div id="b">
		b
		<div id="c">c</div>
	</div>
</div>
複製代碼

那麼捕獲是什麼意思呢?

弓箭射過來,沒穿過一個盒子,就捕獲一次,這個過程就是捕獲過程。 而下面的就是冒泡

捕獲和冒泡會影響到事件的執行順序

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕獲
a.addEventListener("click", function(){
	alert("b-a")
},true)
b.addEventListener("click", function(){
	alert("b-b")
},true)
c.addEventListener("click", function(){
	alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
	alert("m-a")
},false)
b.addEventListener("click", function(){
	alert("m-b")
},false)
c.addEventListener("click", function(){
	alert("m-c")
},false)
複製代碼

上面的代碼的執行順序爲:b-a,b-b,b-c,m-c,m-b,m-a。先執行的捕獲在是冒泡。得出:同時存在捕獲與冒泡時,捕獲的優先級是高於冒泡的

下面,咱們變一下代碼:

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕獲
a.addEventListener("click", function(){
	alert("b-a")
},true)
b.addEventListener("click", function(){
	alert("b-b")
}) // 此處不在添加捕獲事件,那麼就是綁定一個默認的事件
c.addEventListener("click", function(){
	alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
	alert("m-a")
},false)
b.addEventListener("click", function(){
	alert("m-b")
},false)
c.addEventListener("click", function(){
	alert("m-c")
},false)
複製代碼

此時的執行順序爲:b-a,b-c,m-c,b-b,m-b,m-a

再來:

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕獲
a.addEventListener("click", function(){
	alert("b-a")
},true)


b.addEventListener("click", function(){
	alert("m-b")
},false) // 把b的冒泡放在這裏來了
b.addEventListener("click", function(){
	alert("b-b")
}) // 此處不在添加捕獲事件,那麼就是綁定一個默認的事件。即冒泡


c.addEventListener("click", function(){
	alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
	alert("m-a")
},false)
c.addEventListener("click", function(){
	alert("m-c")
},false)
複製代碼

此時的執行順序爲:b-a,b-c,m-c,m-b,b-b,m-a 得出,沒有捕獲的時候誰在前面先執行誰

OK。事件綁定就此結束。下面說說取消事件綁定吧。若是要取消一個使用addEventListener綁定的事件函數,使用removeEventListener能夠移除事件。

與添加事件一致。不過若是使用這個,最好把這個函數給單離拿出來。

中止傳播

使用stopPropagation能夠阻止事件的傳播。不能使用return false

var a = document.getElementById("a");
var b = document.getElementById("b");
var c = document.getElementById("c");
// 捕獲
a.addEventListener("click", function(){
	alert("b-a")
},true)
b.addEventListener("click", function(){
	alert("b-b")
})
c.addEventListener("click", function(){
	alert("b-c")
},true)

// 冒泡
a.addEventListener("click", function(){
	alert("m-a")
})
b.addEventListener("click", function(){
	alert("m-b")
},false)

// 阻止冒泡
c.addEventListener("click", function(e){
	alert("m-c")
	e.stopPropagation(); // 此處阻止傳播
},false)
複製代碼

此時的順序:b-a,b-c,m-c。不會傳遞,後面的不會執行了。阻止捕獲也是同樣,添加以後就不會在繼續往下傳遞了。

這裏有涉及到一個阻止事件的默認行爲preventDefault或者是前面提到的return false

對於IE下的事件綁定

適用與IE6,7,8 IE的事件與模型與W3C的標準事件相比,主要是如下三點不一樣:

  1. 綁定事件的函數不一樣,IE中使用attachEvent()和detachEvent()
  2. 事件必須加上on
  3. IE6模型中,不支持捕獲,只支持冒泡
  4. IE中還有毛病,先綁定的事件後發生(準確的說是隨機發生)
  5. IE中this指向window

更新與2017年12月2日14:30:05

關於使用addEventListener

給元素添加事件通常使用addEventListener的方式來添加,這樣才能夠個一個元素添加多個事件。可是因爲addEventListener單詞太長,容易寫錯,而且代碼壓縮的時候不會壓縮,因此通常不多直接使用他,而是使用函數把他封裝起來使用,避免出錯:

function addEvent(ele,type,fn){
	ele.addEventListener(type,function(e){
		fn(e)
	})
}
複製代碼

使用以上的方式能夠減小出錯率以及方便

關於事件代理(委託)

通常狀況下,若是一個元素下存在多個點擊事件,代碼結構以下:

<ul id="box">
	<li>list-1</li>
	<li>list-2</li>
	<li>list-3</li>
	<li>list-4</li>
</ul>
複製代碼

此時,若是你要給每個li標籤添加一個點擊事件,彈出每個li的索引值,初學者可能會使用for循環的方式來添加:

var oLis  = document.getElementsByTagName("li");

for (var i = 0; i < oLis.length; i++) {
	oLis[i].i = i;
	addEvent(oLis[i],"click",function(e){
		alert(this.i)
	})
}
複製代碼

或者是使用閉包:

var oLis  = document.getElementsByTagName("li");

for (var i = 0; i < oLis.length; i++) {
	(function(i){
		addEvent(oLis[i],"click",function(e){
			alert(i)
		})
	})(i)
}
複製代碼

可是以上兩種都不是一個最好的方法,由於你的li的個數可能發生改變,若是是這樣的話,可能會出一些問題。那麼,此時若是使用事件代理的方式,效果會更好。 事件代理代碼:

var oBox = document.getElementById("box");

addEvent(oBox,'click',function(e){
	var target = e.target;
	// 判斷點擊的是li
	if ( target.nodeName == 'LI' ) {
		alert(target.innerHTML)
	}
})
複製代碼

這樣也是能夠的,不過此時的addEvent函數點擊的時候就須要在fn裏面判斷點擊的是哪個標籤。爲了更好的使用addEvent,咱們能夠改進一下:

function addEvent(ele,type,selector,fn){
	// 若是隻有三個參數,那麼3,4互換
	if ( fn == null ) {
		fn = selector;
		selector = null
	}
	ele.addEventListener(type,function(e){
		var target;
		if ( selector ) {
			// 代理
			target = e.target;
			if(target.matches(selector)){
				fn.call(target.e)
			}
		} else {
			// 不代理
			fn(e)
		}
	})
}
複製代碼

這時點擊li彈出innerHTML就能夠這樣實現

addEvent(oBox,'click','li',function(e){
	alert(this.innerHTML)
})
複製代碼
相關文章
相關標籤/搜索