深入学习jquery源码之bind()与delegate()

bind(type,[data],fn)

概述

为每个匹配元素的特定事件绑定事件处理函数。

参数

type,[data],function(eventObject) String,Object,Function

type: 含有一个或多个事件类型的字符串,由空格分隔多个事件。比如"click"或"submit",还可以是自定义事件名。

data:作为event.data属性值传递给事件对象的额外数据对象

fn:绑定到每个匹配元素的事件上面的处理函数

type,[data],false  String,Object,bool

type:含有一个或多个事件类型的字符串,由空格分隔多个事件。比如"click"或"submit",还可以是自定义事件名。

data:作为event.data属性值传递给事件对象的额外数据对象

false: 将第三个参数设置为false会使默认的动作失效。

events  String

一个或多个事件类型的字符串和函数的数据映射来执行他们。

使用

当每个段落被点击的时候,弹出其文本。

$("p").bind("click", function(){
alert( $(this).text() );
});

同时绑定多个事件类型

$('#foo').bind('mouseenter mouseleave', function() {
$(this).toggleClass('entered');
});

同时绑定多个事件类型/处理程序

$("button").bind({
click:function(){$("p").slideToggle();},
mouseover:function(){$("body").css("background-color","red");},
mouseout:function(){$("body").css("background-color","#FFFFFF");}
});

你可以在事件处理之前传递一些附加的数据。

function handler(event) {
alert(event.data.foo);
}
$("p").bind("click", {foo: "bar"}, handler)

通过返回false来取消默认的行为并阻止事件起泡。

$("form").bind("submit", function() { return false; })

通过使用 preventDefault() 方法只取消默认的行为。

$("form").bind("submit", function(event){
event.preventDefault();
});

通过使用 stopPropagation() 方法只阻止一个事件起泡。

$("form").bind("submit", function(event){
event.stopPropagation();
});

 

unbind(type,[data|fn]])

概述

bind()的反向操作,从每一个匹配的元素中删除绑定的事件。

如果没有参数,则删除所有绑定的事件。

你可以将你用bind()注册的自定义事件取消绑定。

如果提供了事件类型作为参数,则只删除该类型的绑定事件。

如果把在绑定时传递的处理函数作为第二个参数,则只有这个特定的事件处理函数会被删除。

参数

type,[fn] String,Function

type:删除元素的一个或多个事件,由空格分隔多个事件值。

fn:要从每个匹配元素的事件中反绑定的事件处理函数

type,false String,bool 

type:删除元素的一个或多个事件,由空格分隔多个事件值

false:设置为false会使默认的动作失效。

eventObj String

事件对象。这个 eventObj 参数来自事件绑定函数

把所有段落的所有事件取消绑定

$("p").unbind()

将段落的click事件取消绑定

$("p").unbind( "click" )

删除特定函数的绑定,将函数作为第二个参数传入

var foo = function () {
// 处理某个事件的代码
};

$("p").bind("click", foo); // ... 当点击段落的时候会触发 foo

$("p").unbind("click", foo); // ... 再也不会被触发 foo

 

delegate(selector,[type],[data],fn)

概述

指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。

使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)。

参数

selector,[type],fn String,String,Function

selector:选择器字符串,用于过滤器触发事件的元素。

type:附加到元素的一个或多个事件。 由空格分隔多个事件值。必须是有效的事件。

fn:当事件发生时运行的函数

selector,[type],[data],fn String,String,Object,Function

selector:选择器字符串,用于过滤器触发事件的元素。

type:附加到元素的一个或多个事件。由空格分隔多个事件值。必须是有效的事件。

data:传递到函数的额外数据

fn:当事件发生时运行的函数

selector,events String,String

selector:选择器字符串,用于过滤器触发事件的元素。

events:一个或多个事件类型的字符串和函数的数据映射来执行他们。

当点击鼠标时,隐藏或显示 p 元素:

<div style="background-color:red">
<p>这是一个段落。</p>
<button>请点击这里</button>
</div>
$("div").delegate("button","click",function(){
$("p").slideToggle();
});

delegate这个方法可作为live()方法的替代,使得每次事件绑定到特定的DOM元素。

以下两段代码是等同的:

$("table").delegate("td", "hover", function(){
$(this).toggleClass("hover");
});
$("table").each(function(){
$("td", this).live("hover", function(){
$(this).toggleClass("hover");
});

});

 

undelegate([selector,[type],fn])

概述

删除由 delegate() 方法添加的一个或多个事件处理程序。

参数

selector,[type] String,String

selector:需要删除事件处理程序的选择器。

type:需要删除处理函数的一个或多个事件类型。 由空格分隔多个事件值。必须是有效的事件。

selector,[type],fn String,String,Function

selector:需要删除事件处理程序的选择器。

type:需要删除处理函数的一个或多个事件类型。 由空格分隔多个事件值。必须是有效的事件。

fn:要删除的具体事件处理函数。

selector,events String,String 

selector:需要删除事件处理程序的选择器。

events:一个或多个事件类型的字符串和函数的数据映射来执行他们。

namespace String

namespace:一个字符串,其中包含一个命名空间取消绑定的所有事件。

从p元素删除由 delegate() 方法添加的所有事件处理器:

$("p").undelegate();

从p元素删除由 delegate() 方法添加的所有click事件处理器:

$("p").undelegate( "click" )

从form元素删除由 delegate() 方法添加的".whatever"命名空间:

var foo = function () {
//.....
};
//用delegate() 方法给click事件增加".whatever"命名空间
$("form").delegate(":button", "click.whatever", foo);
$("form").delegate("input[type='text']", "keypress.whatever", foo);

// 用undelegate()方法删除delegate()方法增加的".whatever"命名空间
$("form").undelegate(".whatever");

 

live(type, [data], fn)

概述

jQuery 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。

这个方法是基本是的 .bind() 方法的一个变体。使用 .bind() 时,选择器匹配的元素会附加一个事件处理函数,而以后再添加的元素则不会有。为此需要再使用一次 .bind() 才行。比如说

<body>
<div class="clickme">Click here</div>
</body>

可以给这个元素绑定一个简单的click事件:

$('.clickme').bind('click', function() {
alert("Bound handler called.");
});

当点击了元素,就会弹出一个警告框。然后,想象一下这之后有另一个元素添加进来了。

$('body').append('<div class="clickme">Another target</div>');

尽管这个新的元素也能够匹配选择器 ".clickme" ,但是由于这个元素是在调用 .bind() 之后添加的,所以点击这个元素不会有任何效果。

.live() 就提供了对应这种情况的方法。如果我们是这样绑定click事件的:

$('.clickme').live('click', function() {
alert("Live handler called.");
});

然后再添加一个新元素:

$('body').append('<div class="clickme">Another target</div>');

然后再点击新增的元素,他依然能够触发事件处理函数。

事件委托

.live() 方法能对一个还没有添加进DOM的元素有效,是由于使用了事件委托:绑定在祖先元素上的事件处理函数可以对在后代上触发的事件作出回应。传递给 .live() 的事件处理函数不会绑定在元素上,而是把他作为一个特殊的事件处理函数,绑定在 DOM 树的根节点上。在我们的例子中,当点击新的元素后,会依次发生下列步骤:

  1. 生成一个click事件传递给 来处理
  2. 由于没有事件处理函数直接绑定在 <divgt; 上,所以事件冒泡到DOM树上
  3. 事件不断冒泡一直到DOM树的根节点,默认情况下上面绑定了这个特殊的事件处理函数。
  4. 执行由 .live() 绑定的特殊的 click 事件处理函数。
  5. 这个事件处理函数首先检测事件对象的 target 来确定是不是需要继续。这个测试是通过检测 $(event.target).closest('.clickme') 能否找到匹配的元素来实现的。
  6. 如果找到了匹配的元素,那么调用原始的事件处理函数。

由于只有在事件发生时才会在上面的第五步里做测试,因此在任何时候添加的元素都能够响应这个事件。

附加说明

.live() 虽然很有用,但由于其特殊的实现方式,所以不能简单的在任何情况下替换 .bind()。主要的不同有:

  • 在jQuery 1.4中,.live()方法支持自定义事件,也支持所有的 JavaScript 事件。在jQuery 1.4.1中,甚至也支持 focus 和 blue 事件了(映射到更合适,并且可以冒泡的focusin和focusout上)。另外,在jQuery 1.4.1中,也能支持hover(映射到"mouseenter mouseleave")。然而在jQuery 1.3.x中,只支持支持的JavaScript事件和自定义事件:click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, 和 mouseup.
  • .live() 并不完全支持通过DOM遍历的方法找到的元素。取而代之的是,应当总是在一个选择器后面直接使用 .live() 方法,正如前面例子里提到的。
  • 当一个事件处理函数用 .live() 绑定后,要停止执行其他的事件处理函数,那么这个函数必须返回 false。 仅仅调用 .stopPropagation() 无法实现这个目的。

参考 .bind() 方法可以获得更多关于事件绑定的信息。

在jQuery 1.4.1 中,.live() 能接受多个,用空间分隔事件,在提供类似.bind()的功能 。例如,我们可以“live ” 同时绑定mouseover和mouseout事件,像这样:

$('.hoverme').live('mouseover mouseout', function(event) {
if (event.type == 'mouseover') {
// do something on mouseover
} else {
// do something on mouseout
}
});

在jQuery 1.4.3中:你可以绑定一个或多个事件类型的字符串和函数的数据映射来执行他们

$("a").live({
click: function() {
// do something on click
},
mouseover: function() {
// do something on mouseover
}
});

在jQuery 1.4 中,data参数可以用于把附加信息传递给事件处理函数。一个很好的用处是应付由闭包导致的问题。可以参考 .bind() 的讨论来获得更多信息。

在jQuery 1.4 中, live事件可以绑定到“context”DOM元素,而不是默认的文档的根。要设置此背景下,我们通过在一个单一的DOM元素(而不是一个jQuery集合或选择器)使用jQuery() function's second argument。

$('div.clickme', $('#container')[0]).live('click', function() {
// Live handler called.
});

参数

type,[fn] String,Function

type:一个或多个事件类型,由空格分隔多个事件。

fn:要从每个匹配元素的事件中反绑定的事件处理函数

type,[data],false String,Array,bool

type:一个或多个事件类型,由空格分隔多个事件。

data:传递给事件处理函数的附加参数

false:设置为false会使默认的动作失效。

event String 

一个或多个事件类型的字符串和函数的数据映射来执行他们

点击生成的p依然据有同样的功能。

<p>Click me!</p>
$("p").live("click", function(){
$(this).after("<p>Another paragraph!</p>");
});

阻止默认事件行为和事件冒泡,返回 false

$("a").live("click", function() { return false; });

仅仅阻止默认事件行为

$("a").live("click", function(event){
event.preventDefault();
});

 

die(type, [fn])

概述

从元素中删除先前用.live()绑定的所有事件.(此方法与live正好完全相反。)

如果不带参数,则所有绑定的live事件都会被移除。

你可以解除用live注册的自定义事件。

如果提供了type参数,那么会移除对应的live事件。

如果也指定了第二个参数function,则只移出指定的事件处理函数。

参数

type[,fn] String,Function

type:要移除的一个或多个事件处理程序。由空格分隔多个事件值。必须是有效的事件。

fn:要移除的函数。

type String

要移除的一个或多个事件处理程序。 由空格分隔多个事件值。必须是有效的事件。 

给按钮解除click事件

function aClick() {
$("div").show().fadeOut("slow");
}
$("#unbind").click(function () {
$("#theone").die("click", aClick)
});

 

jquery源码

jQuery.fn.extend({
bind: function (types, data, fn) {
return this.on(types, null, data, fn);
},
unbind: function (types, fn) {
return this.off(types, null, fn);
},

delegate: function (selector, types, data, fn) {
return this.on(types, selector, data, fn);
},
undelegate: function (selector, types, fn) {
// ( namespace ) or ( selector, types [, fn] )
return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
}
});