事件委托和jQuery事件绑定

来源:互联网 发布:深圳软件基地 编辑:程序博客网 时间:2024/04/28 05:34

事件委托

什么是事件委托?用现实中的理解就是:100个学生在同一天的中午都要收取快递,这100个学生难道都会在门口等着么?不会,他们会委托门卫代收,然后门卫再逐个将包裹交到学生手中。在jQuery中我们会通过事件冒泡的特性,让子元素的事件绑定到祖先元素上去,在祖先元素统一处理。如果我们项目中有个2000行的列表,每行都有个一个删除button。如果使用.bind来处理,需要绑定2000次到删除button上,这就好比2000个学生同时在校门口收快递,会不断的阻塞道路,还会出现怪异的行为。这种情况放到页面上也是一样,会导致界面效率低下,UI代码不够灵活。而且这2000行数据肯定会用ajax分页的,.bind无法绑定下一页行中的删除button。这就好比,新转入的学生快递员是无法验证他的身份。这时我们就需要用到事件委托,将事件处理放到所有删除button共有的祖先元素上,这个祖先元素根据自己的情况,可能是table标签,可能是一个div标签,也可能是body标签。

利用jQuery实现事件绑定和解绑

jQuery中提供了.bind()和unbind()、.live()和die()、delegate()和undelegate()、on()和off()和one()来实现事件的绑定和解绑。下面我们将分别介绍这四种事件绑定和解绑的的方法。

.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;}
$(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)处  });});

先给大家推荐一个在线编译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()的反向操作,从每一个匹配的元素上删除特定事件的处理函数。例如:
$("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的特殊版)。

总结

.bind()和off ()(off()是使用事件委托绑定事件中jQuery最建议使用的一个,比较典型,所以那它来和.bind()做比较)分别在什么情况下使用呢?
两个原则:DOM中多个元素需要绑定相同的事件处理函数时;DOM中未生成的元素需要绑定和DOM已有元素相同的事件处理函数时;满足这两个条时,使用off()。否则使用.bind();
本文参考了jQuery文档和此博客http://www.itnose.net/detail/6094205.html。以前在使用jQuery做事件绑定是,只是用过click() 函数绑定过单击事件,今天看了一个JS框架,发现好多东西就没有接触过。和事件绑定相关的总结到此文章里。一开始看jQuery文档也是一头雾水,根本看不懂,最后到网上看了一些资料(比较通俗易懂的),在回头看jQuery文档,发现Jquery文档就是jQuery文档,简洁明了,信息量大呀。先去民间看看,在能看懂官方的。








1 0
原创粉丝点击