转】jQuery的.bind()、.live()和.delegate()之间差别
![](http://www.byywee.com/images/Img_line.gif)
Admin
2011年8月9日 名人名言:友情是天堂,没有它就象下地狱;友情是生命,没有它就意味着死亡;你在人间所做的一切,无一不是为了友情。——威·莫里斯
起首看看live()与bind()两种给元素绑定事务的办法的差别是什么??
live()给所有匹配的元素附加一个事务处理惩罚函数,即使这个元素是今后再添加进来的也有效。
这个办法是根蒂根基是的 .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>"");
然后再点击新增的元素,他依然可以或许触发事务处理惩罚函数。
看完以上的解析可能的懂得.bind()和.live()两者的差别,然则这只是知其然,要知其所以然还得弄懂以下的解析:
jQuery的.bind()、.live()和.delegate()之间的差别并非老是那么明显的,然而,若是我们对所有的不合之处都有清楚的懂得的话,那么这将会有助于我们编写出加倍简洁的代码,以及防止在交互应用中弹失足误。
根蒂根基要素
DOM树
起首,可视化一个HMTL文档的DOM树是很有帮助的。一个简单的HTML页面看起来就像是这个样子:
事务冒泡(又称事务传播)
当我们点击一个链接时,其触发了链接元素的单击事务,该事务则激发任何我们已绑定到该元素的单击事务上的函数的履行。
1. ¥(""a"").bind(""click"", function() { alert("That tickles!") });
是以一个单击操纵会触发alert函数的履行。
click事务接着会向树的根标的目标传播,广播到父元素,然后接着是每个祖先元素,只如果它的某个后代元素上的单击事务被触发,事务就会传给它。
在把持DOM的语境中,document是根节点。
如今我们可以较轻易地申明.bind()、.live()和.delegate()的不合之处了。
.bind()
1. ¥(""a"").bind(""click"", function() { alert("That tickles!") });
这是最简单的绑定办法了。JQuery扫描文档找出所有的¥(‘a’)元素,并把alert函数绑定到每个元素的click事务上。
.live()
1. ¥(""a"").live(""click"", function() { alert("That tickles!") });
JQuery把alert函数绑定到¥(document)元素上,并应用’click’和’a’作为参数。任何时辰只要有事务冒泡到document节点上,它就查看该事务是否是一个click事务,以及该事务的目标元素与’a’这一CSS选择器是否匹配,若是都是的话,则履行函数。
live办法还可以被绑定到具体的元素(或“context”)而不是document上,像如许:
1. ¥(""a"", ¥(""#container"")[0]).live(...);
.delegate()
1. ¥(""#container"").delegate(""a"", ""click"", function() { alert("That tickles!") });
JQuery扫描文档查找¥(‘#container’),并应用click事务和’a’这一CSS选择器作为参数把alert函数绑定到¥(‘#container’)上。任何时辰只要有事务冒泡到¥(‘#container’)上,它就查看该事务是否是click事务,以及该事务的目标元素是否与CCS选择器相匹配。若是两种搜检的成果都为真的话,它就履行函数。
可以重视到,这一过程与.live()类似,然则其把处理惩罚法度绑定到具体的元素而非document这一根上。精明的JS’er们可能会做出如许的结论,即¥(""a"").live()
== ¥(document).delegate(""a""),是如许吗?嗯,不,不美满是。
为什么.delegate()要比.live()好用
基于几个原因,人们凡是更愿意选用jQuery的delegate办法而不是live办法。推敲下面的例子:
1. ¥(""a"").live(""click"", function() { blah() });
2.
3. // 或者
4.
5. ¥(document).delegate(""a"", ""click"", function() { blah() });
速度
后者实际上要快过前者,因为前者起首要扫描全部的文档查找所有的¥(‘a’)元素,把它们存成jQuery对象。尽管live函数仅须要把’a’作为串参数传递以用做之后的断定,然则¥()函数并未“知道”被链接的办法将会是.live()。
而另一方面,delegate办法仅须要查找并存储¥(document)元素。
一种寻求避开这一题目的办法是调用在¥(document).ready()之外绑定的live,如许它就会立即履行。在这种体式格式下,其会在DOM获得填充之前运行,是以就不会查找元素或是创建jQuery对象了。
灵活性和链才能
live函数也挺令人费解的。想想看,它被链到¥(‘a’)对象集上,但其实际上是在¥(document)对象上产生感化。因为这个原因,它可以或许试图以一种吓死人的体式格式来把办法链到自身上。实际上,我想说的是,以¥.live(‘a’,…)这一情势作为一种全局性的jQuery办法,live办法会更具意义一些。
仅支撑CSS选择器
最后一点,live办法有一个很是大的毛病,那就是它仅能针对直接的CSS选择器做操纵,这使得它变得很是的不灵活。
欲懂得更多关于CSS选择器的毛病,请参阅Exploring
jQuery .live() and .die()一文。
更新:感激Hacker News上的pedalpete和后面评论中的Ellsass提示我参加接下来的这一节内容。
为什么选择.live()或.delegate()而不是.bind()
毕竟成果,bind看起来似乎加倍的明白和直接,莫非不是吗?嗯,有两个原因让我们更愿意选择delegate或live而不是bind:
1为了把处理惩罚法度附加到可能还未存在于DOM中的DOM元素之上。因为bind是直接把处理惩罚法度绑定到各个元素上,它不克不及把处理惩罚法度绑定到还未存在于页面中的元素之上。
2若是你运行了¥(‘a’).bind(…),而后新的链接经过AJAX参加到了页面中,则你的bind处理惩罚法度对于这些新参加的链接来说是无效的。而另一方面live和delegate则是被绑定到另一个祖先节点上,是以其对于任何今朝或是将来存在于该祖先元素之内的元素都是有效的。
3或者为了把处理惩罚法度附加到单个元素上或是一小组元素之上,监听后代元素上的事务而不是轮回遍历并把同一个函数逐个附加到DOM中的100个元素上。把处理惩罚法度附加到一个(或是一小组)祖先元素上而不是直接把处理惩罚法度附加到页面中的所有元素上,这种做法带来了机能上的益处。
停止传播
最后一个我想做的提示与事务传播有关。凡是景象下,我们可以经由过程应用如许的事务办法来终止处理惩罚函数的履行:
1. ¥(""a"").bind(""click"", function(e) {
2. e.preventDefault();
3. // 或者
4. e.stopPropagation();
5. });
不过,当我们应用live或是delegate办法的时辰,处理惩罚函数实际上并没有在运行,须要比及事务冒泡处处理惩罚法度实际绑定的元素上时函数才会运行。而到此时为止,我们的其他的来自.bind()的处理惩罚函数早已运行了。
项目组原文转载于:http://developer.51cto.com/art/201103/249694.htm