jquery-事件-on原始碼
談一下Jquery中的bind(),live(),delegate(),on()的區別?
1.bind()
.bind()直接繫結在相應的DOM元素上,可以解決跨瀏覽器的問題。
但是對於動態新增的屬於匹配到的元素,不會被觸發事件的,需要多次繫結,影響效率。
$("#niu").bind('click',function(){
alert("hello niuniu");
});
2.live()
live()通過冒泡的方式來繫結到元素上的,對於動態新增的屬於匹配到的元素,也能夠執行。
但是event.stopPropagation()不再有效了,因為事件已經委託到了document上了。此方法在jQuery1.7的時候已經廢除
$("a").live("click", function() { return false; })
3.delegate()
.delegate()則是通過冒泡的方式來繫結事件到制定元素上(但不是冒泡到document),對後生成的元素也可以繫結相應的事件。
delegate(selector,[type],[data],fn)
$(document).ready(function(){
$("div").delegate("p","click",function(){
$(this).slideToggle();
});
$("button" ).click(function(){
$("<p>這是一個新段落</p>").insertAfter("button");
});
});
4.on()
.on() 方法在被選元素及子元素上新增一個或多個事件處理程式
$(selector).on(event,childSelector,data,function,map)
event:必需。規定要從被選元素移除的一個或多個事件或名稱空間。
childSelector:可選。規定只能新增到指定的子元素上的事件處理程式
data:可選。規定傳遞到函式的額外資料。
function:可選。規定當事件發生時執行的函式。
map:規定事件對映 ({event:function, event:function, …}),包含要新增到元素的一個或多個事件,以及當事件發生時執行的函式。
// Bind
$( "#members li a" ).on( "click", function( e ) {} );
$( "#members li a" ).bind( "click", function( e ) {} );
// Live
$( document ).on( "click", "#members li a", function( e ) {} );
$( "#members li a" ).live( "click", function( e ) {} );
// Delegate
$( "#members" ).on( "click", "li a", function( e ) {} );
$( "#members" ).delegate( "li a", "click", function( e ) {} );
//多個事件
$(document).ready(function(){
$("p").on("mouseover mouseout",function(){
$("p").toggleClass("intro");
});
});
//使用map引數新增多個事件處理程式
$(document).ready(function(){
$("p").on({
mouseover:function(){$("body").css("background-color","lightgray");},
mouseout:function(){$("body").css("background-color","lightblue");},
click:function(){$("body").css("background-color","yellow");}
});
});
$("table.planning_grid").on({
mouseenter: function() {
// Handle mouseenter...
},
mouseleave: function() {
// Handle mouseleave...
},
click: function() {
// Handle click...
}
}, "td");
總結:
1.bind()直接繫結在元素上,當元素很多時,會出現效率問題,不會繫結到在它執行完後動態新增的那些元素上
2.live()僅有一次的事件繫結,繫結到document上而不像.bind()那樣給所有的元素挨個繫結,那些動態新增的elements依然可以觸發
3.delegate()更精確的小範圍使用事件代理,效能優於.live(),它不會把所有的event全部繫結到document,而是由你決定把它放在哪兒。而和.live()相同的地方在於都是用event delegation.
4.on()是 bind()、live() 和 delegate() 方法的新的替代品,提供了一種統一繫結事件的方法
仍然提供了.delegate()的優點,當然如果需要你也可以直接用.bind()
5.on原始碼解析
首先,判斷events是否為物件,若是物件則遍歷events物件,針對每一個屬性繫結on()方法,將events[event]作為fn傳入。然後on方法其實就是對於每一個呼叫物件單獨呼叫jQuery.event.add方法進行事件繫結。另外,bind,live,delegate都是通過on實現的。
on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
var type, origFn;
// Types can be a map of types/handlers
if ( typeof types === "object" ) {
// ( types-Object, selector, data )
if ( typeof selector !== "string" ) {
// ( types-Object, data )
data = data || selector;
selector = undefined;
}
// 遍歷types物件,針對每一個屬性繫結on()方法
// 將types[type]作為fn傳入
for ( type in types ) {
this.on( type, selector, data, types[ type ], one );
}
return this;
}
// 引數修正
// jQuery這種引數修正的方法很好
// 可以相容多種引數形式
// 可見在靈活呼叫的背後做了很多處理
if ( data == null && fn == null ) {
// ( types, fn )
fn = selector;
data = selector = undefined;
} else if ( fn == null ) {
if ( typeof selector === "string" ) {
// ( types, selector, fn )
fn = data;
data = undefined;
} else {
// ( types, data, fn )
fn = data;
data = selector;
selector = undefined;
}
}
if ( fn === false ) {
// fn傳入false時,阻止該事件的預設行為
// function returnFalse() {return false;}
fn = returnFalse;
} else if ( !fn ) {
return this;
}
// one()呼叫on()
if ( one === 1 ) {
origFn = fn;
fn = function( event ) {
// Can use an empty set, since event contains the info
// 用一個空jQuery物件,這樣可以使用.off方法,
// 並且event帶有remove事件需要的資訊
jQuery().off( event );
return origFn.apply( this, arguments );
};
// Use same guid so caller can remove using origFn
// 事件刪除依賴於guid
fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
}
// 這裡呼叫jQuery的each方法遍歷呼叫on()方法的jQuery物件
// 如$('li').on(...)則遍歷每一個li傳入add()
// 推薦使用$(document).on()或者集合元素的父元素
return this.each( function() {
jQuery.event.add( this, types, fn, data, selector );
});
},