事件委託和jQuery事件繫結
阿新 • • 發佈:2019-01-05
事件委託
什麼是事件委託?用現實中的理解就是:100個學生在同一天的中午都要收取快遞,這100個學生難道都會在門口等著麼?不會,他們會委託門衛代收,然後門衛再逐個將包裹交到學生手中。在jQuery中我們會通過事件冒泡的特性,讓子元素的事件繫結到祖先元素上去,在祖先元素統一處理。如果我們專案中有個2000行的列表,每行都有個一個刪除button。如果使用.bind來處理,需要繫結2000次到刪除button上,這就好比2000個學生同時在校門口收快遞,會不斷的阻塞道路,還會出現怪異的行為。這種情況放到頁面上也是一樣,會導致介面效率低下,UI程式碼不夠靈活。而且這2000行資料肯定會用ajax分頁的,.bind無法繫結下一頁行中的刪除button。這就好比,新轉入的學生快遞員是無法驗證他的身份。這時我們就需要用到事件委託,將事件處理放到所有刪除button共有的祖先元素上,這個祖先元素根據自己的情況,可能是table標籤,可能是一個div標籤,也可能是body標籤。利用jQuery實現事件繫結和解綁
.bind()和unbind()
.bind()給所有匹配的元素附件一個特定事件的處理的函式。假設我們有這麼一個需求:1、有個10行4列的table,每個單元格被單擊時,當前單元格背景變為藍色。2、點選某個button阻止單元格的預設事件和事件向上冒泡。實現如下:table { width: 400px; height:240px; border:1px solid blue; } table td{ border:1px solid black; width:100px; }
先給大家推薦一個線上編譯java、c、c++、JavaScript/HTML/CSS/等其它語言的線上編譯網站。http://c.runoob.com/。現在基本上能滿足我的學習需要,做個小示例和測試什麼的都是很方便的。 在推薦一個jQuery線上編譯器,本文示例以這個線上編譯器的效果為準。 解釋一下什麼是觸發事件的元素的預設行為和預設事件向上冒泡。 前者指的是:比如<a href="www.baidu.com"></a>,a標籤的click事件預設行為是開啟百度。我們可以在jQuery中使用 event.preventDefault(); 來阻止預設行為的發生。 後者指的是:阻止事件向祖先元素傳遞。比如點選單元格時,觸發了單元格祖先元素(table)的click事件,彈出了“ABC”。我們在jQuery中使用event.stopPropagation();阻止事件向上傳遞。 (1)處包含了這兩者的含義。 .unbind()。.bind()的反向操作,從每一個匹配的元素上刪除特定事件的處理函式。例如:$(document).ready(function(){ var row = 10, col = 4; var $table = $("<table></table>"); for(var i=0;i<row;i++){ var $tr = $("<tr></tr>"); for(var j=0;j<col;j++){ $("<td></td>").appendTo($tr); } $table.append($tr); } $("body").append($table); //使用.bind為每個匹配的click事件繫結處理函式 $("table td").bind("click", function(event){<span style="white-space:pre"> </span>//(2)處 $(this).css({backgroundColor:"#00F"}); }); $("table").bind("click", function(event){ alert("ABC"); }); //新增一個button var $but = $("<button>阻止td的預設行為和事件向上冒泡</button>").appendTo("body"); //阻止td的預設行為和事件向上冒泡 $but.bind("click", function(){ //這裡返回false有 兩個含義,阻止單元格的預設行為和事件向上冒泡 $("table td").bind("click", function(){ return false; }); //(1)處 }); });
$("table td").unbind("click");<span style="white-space:pre"> </span>//只解綁click事件
$("table td").unbind();<span style="white-space:pre"> </span>//解綁所有事件
.live()和die()
我們來擴充套件一下.bind()和unbind()節中的示例,擴充套件功能為:點選一個按鈕在table的最後一行後新增一個新行,使這個新行具有和其它單元格一行的單擊行為。使用.live()就可以解決這個需求,.live()給所有匹配的元素添一個特定事件的處理函式,即使這個元素是後新增進來的。這樣就省去了在新增這個新行時,程式碼顯示的在呼叫.bind()。完整程式碼如下:<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/1.6.2/jquery.min.js"></script>
</head>
<body>
</body>
</html>
table {
width: 400px;
height:240px;
border:1px solid blue;
}
table td{
border:1px solid black;
width:100px
}
$(document).ready(function(){
var row = 10, col = 4;
var $table = $("<table></table>");
for(var i=0;i<row;i++){
var $tr = $("<tr></tr>");
for(var j=0;j<col;j++){
$("<td></td>").appendTo($tr);
}
$table.append($tr);
}
$("body").append($table);
//使用.live為每個匹配元素的click事件繫結處理函式
$("table td").live("click", function(event){
$(this).css({backgroundColor:"#00F"});
});
$("table").bind("click", function(event){
alert("ABC");
});
//使用.die()解綁click事件函式
var $but1 = $("<button>取消繫結事件</button>").appendTo("body");
$but1.bind("click", function(){
$("table td").die("click");
})
});
其實.live()是.bind()的一種變體。但是實現原理兩者卻大不相同。.bind()是為每一個匹配的元素都繫結一個特定的處理函式。而.live()使用的是事件委託原理實現的,委託給了$(docuemnt)物件來處理,不會繫結到匹配的每個元素上,所以一個元素在之後新增進來,只要這個這個元素匹配選擇器($("table td"))就可以觸發繫結到$(document)物件的事件處理函式。 在我們上面的例子中,當點選新新增的行,會一次發生以下步驟: 1,生成一個事件物件,用來傳遞給處理函式 2,由於事件處理函式沒有直接繫結到新行上,事件向上冒泡(向上傳遞click事件) 3,事件不斷向上冒泡一直到DOM樹的根節點 4,觸發繫結到DOM樹根節點的事件處理函式 5,這個事件處理函式首先檢測事件源元素是否是匹配"table td"選擇器(這是為了防止其他其它標籤的事件也觸發.live()上繫結的函式)。 6,如果匹配就執行在.live上繫結的函式。 感興趣的同學可以瞭解一下事件冒泡和事件捕獲,瞭解了這兩個東西,才能更好的理解事件委託。這裡只是講解了.live()的用法和原理,具體細節請參見jQuery對.live()的說明。 由於.live()引數的特殊性,不支援鏈式呼叫等諸多不便原因,從jQuery1.4.3開始.live()和die() 不建議被使用,jQuery1.7以後的版本中.live()、die()函式已經被移除。如果使用jQuery1.7+版本話使用on()和off()來代替。如果使用的是1.7-版本的話建議使用delegate()和undelegate()來代替。已經被移除了還說這麼多是為了讓我們更好的理解jQuery的事件繫結和接下來將要介紹的兩組事件繫結函式。
delegate()和undelegate()
jQuery1.4.3開始.live()、die()不建議在被使用。而是建議使用支援鏈式呼叫、語義清晰、減少冒泡層次的.delegate()和undelegate()函式。我們可以通過選擇器指定將事件委託到那個元素上,而不是固定的DOM跟元素。使用者這兩個函式來改寫.live()和 die()節中的示例。程式碼如下(CSS程式碼同上,這裡只貼出了HTML和JS程式碼):<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/1.6.2/jquery.min.js"></script>
<script id="jquery_183" type="text/javascript" class="library" src="/js/sandbox/jquery/jquery-1.8.3.min.js"></script>
</head>
<body>
</body>
</html>
$(document).ready(function(){
var row = 10, col = 4;
var $table = $("<table></table>");
for(var i=0;i<row;i++){
var $tr = $("<tr></tr>");
for(var j=0;j<col;j++){
$("<td></td>").appendTo($tr);
}
$table.append($tr);
}
$("body").append($table);
//使用.delegate為每個匹配元素的click事件繫結處理函式
$("table").delegate("td", "click", function(event){
$(this).css({backgroundColor:"#00F"});
return false; //阻止預設行為和事件向上冒泡,不會彈出 “ABC”
});
$("table").bind("click", function(event){
alert("ABC");
});
//使用undelegate()解綁click事件函式
var $but1 = $("<button>取消繫結事件</button>").appendTo("body");
$but1.bind("click", function(){
$("table").undelegate("td", "click");
})
});
通過上面的示例我們發現事件委託給了$("table"),delegate()的第一個引數是指只有$("table")下的td能觸發給$("table")的事件,$("table")下的其它子元素是不可以的,用於過濾觸發事件的元素。第二個引數事件型別。第三個引數事件處理函式。
on()和off()和one()
jQuery1.7+新增的新的事件處理函式on()、off()和one()整合了delegate()和undelegate()函式。並且提供了更靈活的事件繫結和解綁支援。使用on()、off()來改寫delegate()和undelegate()節的示例,程式碼如下:<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title>
<script type="text/javascript" src="//cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script>
</head>
<body>
</body>
</html>
$(document).ready(function(){
var row = 10, col = 4;
var $table = $("<table></table>");
for(var i=0;i<row;i++){
var $tr = $("<tr></tr>");
for(var j=0;j<col;j++){
$("<td></td>").appendTo($tr);
}
$table.append($tr);
}
$("body").append($table);
//使用.on為每個匹配元素的click事件繫結處理函式
$("table").on("click.row", "td", function(event){
$(this).css({backgroundColor:"#00F"});
return false; //阻止預設行為和事件向上冒泡,不會彈出 “ABC”
});
$("table").bind("click", function(event){
alert("ABC");
});
//使用off()解綁click事件函式
var $but1 = $("<button>取消繫結事件</button>").appendTo("body");
$but1.bind("click", function(){
$("table").off("click", "td");
})
});
off()第一個引數是事件型別,第二個引數是選擇器,第三個引數是事件處理函式。這裡第一個引數click.row比較特殊,click代表事件,row程式碼自定義的名稱空間,這樣在使用off()解綁事件時可用更靈活,比如上例中off("click", “td”)程式碼移除所有click事件,off(".row", "td")代表移除所有.row名稱空間下的事件。 one()為每個匹配的元素繫結一個一次性的事件處理函式,執行一次後,以後將不再觸發,相當於.bind()的一個特殊版(注意喲這裡是.bind的特殊版)。