您的当前位置:首页正文

jQuery事件绑定和委托实例

来源:一二三四网
jQuery事件绑定和委托实例

本⽂实例讲述了jQuery事件绑定和委托。分享给⼤家供⼤家参考。具体⽅法如下:

jQuery事件的绑定和委托可以⽤多种⽅法实现,on() 、 bind() 、 live() 、 delegate() ,还有one()。

有时我们可能会像下⾯这样绑定⼀个事件:复制代码 代码如下:

$(\"#div1\").click(function() { alert(\"点击后触发\"); });

上⾯的事件绑定,我们可以通过多种⽅式去实现:

1. on()

复制代码 代码如下://⽆数据参数

$(\"p\").on(\"click\alert( $(this).text() ); });

//有数据参数

function myHandler(event) { alert(event.data.foo); }

$(\"p\").on(\"click\与on()对应的是off(),⽤来移除事件绑定:

复制代码 代码如下:var foo = function () {

// code to handle some kind of event };

// ... now foo will be called when paragraphs are clicked ... $(\"body\").on(\"click\

// ... foo will no longer be called. $(\"body\").off(\"click\off():移除on()进⾏的绑定one():只绑定⼀次。

2. bind()

参数:

(type,[data],function(eventObject))

type: 含有⼀个或多个事件类型的字符串,由空格分隔多个事件。⽐如\"click\"或\"submit\",还可以是⾃定义事件名。data:作为event.data属性值传递给事件对象的额外数据对象

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

(type,[data],false)

type:含有⼀个或多个事件类型的字符串,由空格分隔多个事件。⽐如\"click\"或\"submit\",还可以是⾃定义事件名。data:作为event.data属性值传递给事件对象的额外数据对象

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

同时绑定多个事件类型:

复制代码 代码如下:

$('#foo').bind('mouseenter mouseleave', function() {

$(this).toggleClass('entered'); });

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

复制代码 代码如下:$(\"button\").bind({

click:function(){$(\"p\").slideToggle();},

mouseover:function(){$(\"body\").css(\"background-color\

mouseout:function(){$(\"body\").css(\"background-color\});

你可以在事件处理之前传递⼀些附加的数据。复制代码 代码如下:

function handler(event) { alert(event.data.foo); }

$(\"p\").bind(\"click\

通过返回false来取消默认的⾏为并阻⽌事件起泡。复制代码 代码如下:

$(\"form\").bind(\"submit\bind存在的问题

如果表格中要绑定单击事件的有10列500⾏,那么查找和遍历5000个单元格会导致脚本执⾏速度明显变慢,⽽保存5000个td元素和相应的事件处理程序也会占⽤⼤量内存(类似于让每个⼈亲⾃站在门⼝等快递)。

在前⾯这个例⼦的基础上,如果我们想实现⼀个简单的相册应⽤,每页只显⽰50张照⽚的缩略图(50个单元格),⽤户点击“第x页”(或“下⼀页”)链接可以通过Ajax从服务器动态加载另外50张照⽚。在这种情况下,似乎使⽤.bind()⽅法为50个单元格绑定事件⼜可以接受了。

事实却不然。使⽤.bind()⽅法只会给第⼀页中的50个单元格绑定单击事件,动态加载的后续页⾯中的单元格都不会有这个单击事件。换句话说,.bind()只能给调⽤它的时候已经存在的元素绑定事件,不能给未来新增的元素绑定事件(类似于新来的员⼯收不到快递)。

事件委托可以解决上述两个问题。具体到代码上,只要⽤jQuery 1.3新增的.live()⽅法代替.bind()⽅法即可:复制代码 代码如下:

$(\"#info_table td\").live(\"click\显⽰更多信息*/});

这⾥的.live()⽅法会把click事件绑定到$(document)对象(但这⼀点从代码中体现不出来,这也是.live()⽅法饱受诟病的⼀个重要原因,稍后再详细讨论),⽽且只需要给$(document)绑定⼀次(不是50次,更不是5000次),然后就能够处理后续动态加载的照⽚单元格的单击事件。在接收到任何事件时,$(document)对象都会检查事件类型和事件⽬标,如果是click事件且事件⽬标是td,那么就执⾏委托给它的处理程序。

unbind():移除bind进⾏的绑定。

3. live()

到⽬前为⽌,⼀切似乎很完美。可惜,事实并⾮如此。因为.live()⽅法并不完美,它有如下⼏个主要缺点:

$()函数会找到当前页⾯中的所有td元素并创建jQuery对象,但在确认事件⽬标时却不⽤这个td元素集合,⽽是使⽤选择符表达式与event.target或其祖先元素进⾏⽐较,因⽽⽣成这个jQuery对象会造成不必要的开销;

默认把事件绑定到$(document)元素,如果DOM嵌套结构很深,事件冒泡通过⼤量祖先元素会导致性能损失;只能放在直接选择的元素后⾯,不能在连缀的DOM遍历⽅法后⾯使⽤,即$(\"#info_table td\").live...可以,但$(\"#info_table\").find(\"td\").live...不⾏;

收集td元素并创建jQuery对象,但实际操作的却是$(document)对象,令⼈费解。解决之道

为了避免⽣成不必要的jQuery对象,可以使⽤⼀种叫做“早委托”的hack,即在$(document).ready()⽅法外部调⽤.live():复制代码 代码如下:(function($){

$(\"#info_table td\").live(\"click\显⽰更多信息*/}); })(jQuery);

在此,(function($){...})(jQuery)是⼀个“⽴即执⾏的匿名函数”,构成了⼀个闭包,可以防⽌命名冲突。在匿名函数内部,$参数引⽤jQuery对象。这个匿名函数不会等到DOM就绪就会执⾏。注意,使⽤这个hack时,脚本必须是在页⾯的head元素中链接和(或)执⾏的。之所以选择这个时机,因为这时候刚好document元素可⽤,⽽整个DOM还远未⽣成;如果把脚本放在结束的body标签前⾯,就没有意义了,因为那时候DOM已经完全可⽤了。

为了避免事件冒泡造成的性能损失,jQuery从1.4开始⽀持在使⽤.live()⽅法时配合使⽤⼀个上下⽂参数:复制代码 代码如下:

$(\"td\显⽰更多信息*/});

这样,“受托⽅”就从默认的$(document)变成了$(\"#info_table\")[0],节省了冒泡的旅程。不过,与.live()共同使⽤的上下⽂参数必须是⼀个单独的DOM元素,所以这⾥指定上下⽂对象时使⽤的是$(\"#info_table\")[0],即使⽤数组的索引操作符来取得的⼀个DOM元素。

4. delegate()

如前所述,为了突破单⼀.bind()⽅法的局限性,实现事件委托,jQuery 1.3引⼊了.live()⽅法。后来,为解决“事件传播链”过长的问题,jQuery 1.4⼜⽀持为.live()⽅法指定上下⽂对象。⽽为了解决⽆谓⽣成元素集合的问题,jQuery 1.4.2⼲脆直接引⼊了⼀个新⽅法.delegate()。

使⽤.delegate(),前⾯的例⼦可以这样写:

复制代码 代码如下:

$(\"#info_table\").delegate(\"td\显⽰更多信息*/});

使⽤.delegate()有如下优点(或者说解决了.live()⽅法的如下问题):

直接将⽬标元素选择符(\"td\")、事件(\"click\")及处理程序与“受拖⽅”$(\"#info_table\")绑定,不额外收集元素、事件传播路径缩短、语义明确;

⽀持在连缀的DOM遍历⽅法后⾯调⽤,即⽀持$(\"table\").find(\"#info\").delegate...,⽀持精确控制;可见,.delegate()⽅法是⼀个相对完美的解决⽅案。但在DOM结构简单的情况下,也可以使⽤.live()。

提⽰:使⽤事件委托时,如果注册到⽬标元素上的其他事件处理程序使⽤.stopPropagation()阻⽌了事件传播,那么事件委托就会失效。

undelegate(): 移除delegate的绑定

希望本⽂所述对⼤家的jQuery程序设计有所帮助。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top