@(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
形式: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官網的一個話 代理
三個參數:
on
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
適用與IE6,7,8 IE的事件與模型與W3C的標準事件相比,主要是如下三點不一樣:
on
this
指向window
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)
})
複製代碼