转自: http://www.keakon.cn/bbs/thread-1308-1-1.html
jQuery的事件处理是非常强大的,然而美中不足的是,它只能对当前存在的jQuery对象绑定事件,这就使得动态创建的对象必须再次绑定事件。
虽然jQuery 1.3推出了live函数,可以自动捕捉新增对象的事件,不过支持的事件较少,且有时会因为其他插件未考虑live函数,没有让事件冒泡而使live失 效。
于是出于好奇,我用了下jQuery帮助文档里提到的
Live Query,结果发现实在太方便了。
它的原理和live不同,是每隔20ms搜索通过livequery注册的事件,并重新查找符合的对象进行绑定。
看上去效率虽然比live低,但实际测试还不错。用IE 6不停创建div,CPU占用率大概23%(我的电脑是1.6G双核的);在创建了几百个后,我停止创建,CPU在1秒内就降到4%,再过一会降为0%。 也就是说这个检测肯定做过优化的。
根据文档的说明,我觉得应该是只会检查新增对象及更改过属性的对象,这个效率应该是不成问题的。
下面用代码来说明它的强大。
首先是绑定click事件:
The xhtml code:
- <input type="button" value="create" id="create" />
- <script type="text/javascript">
- $('#create').click(function () {
- $('<div>点我试试</div>').appendTo('body');
- });
- $('div').bind('click', function () {alert('clicked');});
- //$('div').livequery('click', function () {alert('clicked');});
- //$('div').livequery(function () {$(this).click(function () {alert('clicked');})});
- </script>
<input type="button" value="create" id="create" /> <script type="text/javascript"> $('#create').click(function () { $('<div>点我试试</div>').appendTo('body'); }); $('div').bind('click', function () {alert('clicked');}); //$('div').livequery('click', function () {alert('clicked');}); //$('div').livequery(function () {$(this).click(function () {alert('clicked');})}); </script>
先不要去掉注释,直接看bind方法。点击按钮后创建div,可是点击创建 出来的div完全没反应。原因是bind函数执行时,这些div还没创建,所以不可能绑上事件。
接着换成livequery,方法很简单,直接把bind改成livequery就行了,接口是完全相同的。再试试点击创建的div,发现已经绑上事件 了。
然后看第3种方式,直接给livequery传函数。这种方式最为强大,因为每次livequery发现一个符合条件的新对象,就会执行这个函数,而 this则指向对象本身。所以这种方式除了绑定事件,还能做别的事。
还有种传递2个函数的用法,和前者差不多,只不过第2个函数会在不符合条件时调用,一般是用在hover这种事件。
看完这些代码,似乎觉得livequery也没啥,毕竟live基本上也能做到这些,只不过支持的事件有限。
然而前面我说了,livequery不只是绑定事件,它还能做别的事。
下面就来看个支持jQuery UI的draggable函数的例子:
The xhtml code:
- <style type="text/css">
- div {width: 100px; height: 100px; overflow: hidden; background: blue;}
- </style>
- <input type="button" value="create" id="create" />
- <script type="text/javascript">
- $('#create').click(function () {
- $('<div>拖我试试</div>').appendTo('body');
- });
- $('div').livequery(function () {$(this).draggable();});
- </script>
<style type="text/css"> div {width: 100px; height: 100px; overflow: hidden; background: blue;} </style> <input type="button" value="create" id="create" /> <script type="text/javascript"> $('#create').click(function () { $('<div>拖我试试</div>').appendTo('body'); }); $('div').livequery(function () {$(this).draggable();}); </script>
试试就知道,新创建的div也能绑定拖动,而无需手动绑定。
或许你看不出这意味着什么,但如果draggable要和droppable配合起来,要求draggable对象只能放入符合条件的droppable 对象里,且draggable和droppable对象的属性是随用户操作而不断变化的。
如果不借助livequery,我不得不手动在每次变化属性时都去重设所有的droppable(可能有几十个),而这种变化在代码中可能有上百处。这是 很难保证每次都正确处理的,而且一旦我需要改动条件与droppable的关系,则这上百处都需要检查一遍,以保证一致性。
但假如借助livequery,我可以单独将条件和droppable的关系列出来,用livequery来连接这种关系。之后就能随意更改对象的条件, 而livequery会自动处理绑定新的关系。
虽然这肯定比不上手动绑定的性能,但将关系抽象出来,极大降低了编程的复杂性,是完全值得推荐的。
还是那句话,只有当性能确实成为问题时,才去关注它。如果只是认为它可能会慢一点就不用了,那这个世界也就不会出现C、C++、Java以及动态语言了, 一定还是汇编语言独霸天下的时代。特别是垃圾回收机制,你不觉得和Live Query很相似吗?
话说回来,jQuery的性能肯定比不上手工打造的JavaScript代码,但编程效率却高了至少5倍,所以还不照样很多人用吗?
如果作者能给出个20ms究竟做了什么的说明,并给个处理大量DOM的性能测试的话,估计使用的人会多很多~
最后补充一句,如果用jQuery 1.3.x,则需要去
Git下载对应的1.1.x版,jQuery官网只有 1.0.x的。