编程小贴士

给你的编程提供小点子


怎么理解js中的事件委托

随着DOM结构的复杂化和Ajax等动态脚本技术的运用,事件委托自然浮出了水面。jQuery为绑定和委托事件提供了.bind()、.live()和.delegate()方法。本文在讨论这几个方法内部实现的基础上,展示它们的优劣势及适用场合。

事件委托

事件委托的事例在现实当中比比皆是。比如,有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。
我们知道,DOM在为页面中的每个元素分派事件时,相应的元素一般都在事件冒泡阶段处理事件。在类似 body > div > a 这样的结构中,如果单击a元素,click事件会从a一直冒泡到div和body(即document对象)。因此,发生在a上面的单击事件,div和body元素同样可以处理。而利用事件传播(这里是冒泡)这个机制,就可以实现事件委托。具体来说,事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)。

.bind()

假设有一个多行多列的表格,我们想让用户单击每个单元格都能看到与其中内容相关的更多信息(比如,通过提示条)。为此,可以为每个单元格都绑定click事件:

$("info_table td").bind("click", function(){/*显示更多信息*/});

问题是,如果表格中要绑定单击事件的有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",function(){/*显示更多信息*/});

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

.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",function(){/*显示更多信息*/});
})(jQuery);

在此,(function($){…})(jQuery)是一个“立即执行的匿名函数”,构成了一个闭包,可以防止命名冲突。在匿名函数内部,$参数引用jQuery对象。这个匿名函数不会等到DOM就绪就会执行。注意,使用这个hack时,脚本必须是在页面的head元素中链接和(或)执行的。之所以选择这个时机,因为这时候刚好document元素可用,而整个DOM还远未生成;如果把脚本放在结束的body标签前面,就没有意义了,因为那时候DOM已经完全可用了。
为了避免事件冒泡造成的性能损失,jQuery从1.4开始支持在使用.live()方法时配合使用一个上下文参数:$(“td”,$(“#info_table”)[0]).live(“click”,function(){/显示更多信息/});
这样,“受托方”就从默认的$(document)变成了$(“#info_table”)[0],节省了冒泡的旅程。不过,与.live()共同使用的上下文参数必须是一个单独的DOM元素,所以这里指定上下文对象时使用的是$(“#info_table”)[0],即使用数组的索引操作符来取得的一个DOM元素。

.delegate()

如前所述,为了突破单一.bind()方法的局限性,实现事件委托,jQuery 1.3引入了.live()方法。后来,为解决“事件传播链”过长的问题,jQuery 1.4又支持为.live()方法指定上下文对象。而为了解决无谓生成元素集合的问题,jQuery 1.4.2干脆直接引入了一个新方法.delegate()。
使用.delegate(),前面的例子可以这样写:

$("#info_table").delegate("td","click",function(){/*显示更多信息*/});

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

  • 直接将目标元素选择符(”td”)、事件(”click”)及处理程序与“受拖方”$(“#info_table”)绑定,不额外收集元素、事件传播路径缩短、语义明确;
  • 支持在连缀的DOM遍历方法后面调用,即支持$(“table”).find(“#info”).delegate…,支持精确控制;

可见,.delegate()方法是一个相对完美的解决方案。但在DOM结构简单的情况下,也可以使用.live()。

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

结论

在下列情况下,应该使用.live()或.delegate(),而不能使用.bind():
为DOM中的很多元素绑定相同事件; 为DOM中尚不存在的元素绑定事件;
PS:根据jQuery 1.7 Beta 1的发版说明,jQuery 1.7为了解决.bind()、.live()和.delegate()并存造成的不一致性问题,将会增加一对新的事件方法:.on()和.off(): $(elems).on(events, selector, data, fn);
$(elems).off(events, selector, fn); 如果指定selector,则为事件委托;否则,就是常规绑定。新旧API对应如下:

tips1000_2015-01-21_00-22-5

131 Responses to “ 怎么理解js中的事件委托 ”

  1. i love pron说道:

    n1tOMa Incredible points. Solid arguments. Keep up the great effort.

  2. I think other web-site proprietors should take this website as an model, very clean and great user friendly style and design, as well as the content. You are an expert in this topic!

  3. Kickboxing说道:

    Wow! Thank you! I permanently wanted to write on my website something like that. Can I include a part of your post to my blog?

  4. xem tu vi说道:

    This is one awesome post.Much thanks again. Really Great.

  5. colors for kids说道:

    Usually I do not learn post on blogs, however I wish to say that this write-up very forced me to take a look at and do so! Your writing style has been surprised me. Thanks, very great article.

  6. There is certainly a lot to find out about this subject. I really like all the points you have made.

  7. wow, awesome post.Really thank you! Fantastic.

  8. Really appreciate you sharing this blog article.Really thank you! Great.

  9. Thank you ever so for you article post.Much thanks again. Really Great.

  10. You made some decent points there. I looked on the internet for the issue and found most individuals will go along with with your site.

  11. Oluwadamilare说道:

    that matches all of your pursuits and wishes. On a website primarily based courting earth-wide-internet

  12. Precisely what I was searching for, thanks for posting. There are many victories worse than a defeat. by George Eliot.

  13. this website说道:

    web owners and bloggers made good content as you did, the

  14. dentist说道:

    You, my pal, ROCK! I found exactly the info I already searched everywhere and simply could not locate it. What an ideal web site.

  15. go说道:

    incredibly excellent post, i absolutely actually like this exceptional internet site, carry on it

  16. cialis for sale说道:

    Only wanna tell that this is handy , Thanks for taking your time to write this.

  17. buy说道:

    Thanks for the blog article.Much thanks again. Awesome.

  18. w88world说道:

    This is one awesome blog article. Great.

  19. mebel na zakaz说道:

    Wow, great blog article.Really looking forward to read more. Keep writing.

  20. Really appreciate you sharing this post.Really thank you! Will read on

  21. mca make money说道:

    superb post.Ne aer knew this, thanks for letting me know.

  22. Penn Clothing说道:

    Replica Oakley Sunglasses Replica Oakley Sunglasses

  23. Thanks again for the blog.Really thank you!

  24. Woking taxi说道:

    sarko carla divorce divorce par consentement mutuelle

  25. Really informative article post.Thanks Again.

  26. Wow! Thank you! I constantly needed to write on my blog something like that. Can I take a fragment of your post to my blog?

  27. microblog说道:

    Wow, amazing blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your website is wonderful, as well as the content!

  28. Im grateful for the post.Really thank you! Really Cool.

  29. This can be exactly what I had been searching for, thanks

  30. nonetheless, you command get bought an edginess over

  31. It as hard to come by well-informed people about this topic, however, you sound like you know what you are talking about! Thanks

  32. Really informative post.Really looking forward to read more. Really Cool.

  33. And说道:

    There is definately a lot to learn about this issue. I really like all of the points you ave made.

  34. Wanted to drop a remark and let you know your Rss feed isnt working today. I tried including it to my Google reader account but got nothing.

  35. Get the facts说道:

    I value the post.Really looking forward to read more. Keep writing.

  36. Nwokolo说道:

    What as up, I read your new stuff daily. Your humoristic style is witty, keep up the good work!

  37. klm coupon code说道:

    What blogging website had the least invasive ads for free-account users?. Or what blogging website is best for someone looking to start a professional literary blog?.

  38. just beneath, are a lot of completely not connected websites to ours, on the other hand, they are certainly worth going over

  39. IaаАа’б‚Т€ТšаЂаŒаАа’б‚Т€ТžаБТžve learn a few excellent stuff here. Definitely price bookmarking for revisiting. I wonder how so much attempt you put to make this kind of great informative web site.

  40. Really enjoyed this blog article.Really looking forward to read more. Fantastic.

  41. recycling说道:

    You made some really good points there. I checked on the web to learn more about the issue and found most people will go along with your views on this site.

  42. Justin Bieber说道:

    therefore where can i do it please assist.

  43. craft supplies说道:

    Very informative article.Much thanks again. Really Cool.

  44. truyen ngon tinh说道:

    Say, you got a nice blog.Really looking forward to read more. Will read on

  45. Warehousing Kiev说道:

    You are my breathing in, I have few blogs and often run out from to brand.

  46. I went over this web site and I believe you have a lot of good info, saved to fav (:.

  47. securities说道:

    You need to participate in a contest for probably the greatest blogs on the web. I will recommend this site!

  48. What as up to every single one, it as really a nice for me to visit this web page, it consists of helpful Information.

  49. This blog was how do you say it? Relevant!! Finally I have found something that helped me. Thanks!

  50. Thank you for another excellent article. Where else could anybody get that kind of info in such a perfect way of writing? I ave a presentation next week, and I am on the look for such info.

  51. Say, you got a nice article.Really looking forward to read more. Want more.

  52. Usually I don at read article on blogs, but I wish to say that this write-up very forced me to try and do it! Your writing style has been amazed me. Thanks, quite nice article.

  53. Tattoo Shop说道:

    Thank you for helping out, good information. Whoever obeys the gods, to him they particularly listen. by Homer.

  54. Really enjoyed this post.Much thanks again. Fantastic.

  55. Perfectly pent subject matter, Really enjoyed examining.

  56. Loris说道:

    Very informative blog.Thanks Again. Awesome.

  57. My brother recommended I might like this blog. He was totally right. This post actually made my day. You cann at imagine just how much time I had spent for this information! Thanks!

  58. Your style is very unique in comparison to other people I have read stuff from. I appreciate you for posting when you ave got the opportunity, Guess I all just bookmark this site.

  59. Blogging说道:

    Thank you ever so for you article post.Really looking forward to read more. Much obliged.

  60. girls说道:

    This is a topic which is close to my heart Best wishes! Where are your contact details though?

  61. Really enjoyed this article.Really looking forward to read more. Fantastic.

  62. Your style is really unique in comparison to other folks I have read stuff from. Many thanks for posting when you have the opportunity, Guess I all just book mark this site.

  63. Beyoncé说道:

    say about this article, in my view its in fact

  64. weight loss说道:

    Thank you for sharing your info. I truly appreciate your efforts and I will be waiting for your further write ups thank you once

  65. Como tejer说道:

    You have remarked very interesting points ! ps nice website.

  66. I really value your piece of work, Great post.

  67. local说道:

    Looking forward to reading more. Great blog post.Much thanks again. Really Cool.

  68. white shoes说道:

    Of course, what a splendid website and instructive posts, I definitely will bookmark your website.Have an awsome day!

  69. worth说道:

    Thanks again for the blog post.Really looking forward to read more.

  70. hampton bay说道:

    Wow! This can be one particular of the most helpful blogs We ave ever arrive across on this subject. Actually Wonderful. I am also an expert in this topic so I can understand your hard work.

  71. Waec expo说道:

    It as in reality a nice and useful piece of info. I am happy that you shared this useful tidbit with us. Please keep us up to date like this. Thanks for sharing.

  72. Waec expo说道:

    This blog is definitely educating and also informative. I have chosen a bunch of handy tips out of this amazing blog. I ad love to return every once in a while. Thanks!

  73. I really love your website.. Great colors & theme. Did you develop this web site yourself?

  74. Well I truly enjoyed reading it. This subject provided by you is very effective for accurate planning.

  75. Usually I don at learn article on blogs, however I would like to say that this write-up very pressured me to take a look at and do it! Your writing taste has been amazed me. Thanks, quite great post.

  76. Major thanks for the blog.Thanks Again. Cool.

  77. tm objection说道:

    Thank you for your post.Really looking forward to read more. Fantastic.

  78. This blog is no doubt awesome additionally diverting. I have found helluva helpful stuff out of this amazing blog. I ad love to go back over and over again. Thanks!

  79. Utterly indited content, appreciate it for selective information. Life is God as novel. Let him write it. by Isaac Bashevis Singer.

  80. Your home is valueble for me. Thanks!aаАа’б‚Т€ТšаЂаŒаАТ’аЂа†

  81. Very interesting points you have remarked, thank you for posting.

  82. negocios说道:

    It is actually a great and helpful piece of information. I am glad that you simply shared this helpful info with us. Please keep us up to date like this. Thanks for sharing.

  83. free browsing说道:

    Looking for me, I came here for important information. The information is so incredible that I have to check it out. Nevertheless, thanks.

  84. hotel说道:

    When considering home roofing styles, there are still roofing shovel a

  85. we prefer to honor quite a few other net web-sites on the net, even though they aren

  86. You are my inhalation , I own few web logs and occasionally run out from to post.

  87. It as very easy to find out any topic on web as compared to textbooks, as I found this piece of writing at this website.

  88. In my view, if all webmasters and bloggers made good content as you

  89. Thank you for sharing this very good piece. Very interesting ideas! (as always, btw)

  90. Wow! This could be one particular of the most helpful blogs We ave ever arrive across on this subject. Basically Great. I am also a specialist in this topic so I can understand your effort.

  91. Really appreciate you sharing this blog.Really looking forward to read more. Really Great.

  92. It as hard to find experienced people about this topic, however, you sound like you know what you are talking about! Thanks

  93. Thanks-a-mundo for the article post.Thanks Again. Great.

  94. graham dailies说道:

    This really answered the drawback, thanks!

  95. know more说道:

    I think this is a real great post.Really looking forward to read more. Fantastic.

  96. for details说道:

    This awesome blog is no doubt entertaining as well as diverting. I have found many handy tips out of this blog. I ad love to come back again and again. Thanks a lot!

  97. Thanks for sharing, this is a fantastic article.Really thank you! Keep writing.

  98. is written by him as nobody else know such detailed about my problem.

  99. over here说道:

    you may have an incredible weblog right here! would you like to make some invite posts on my blog?

  100. for more info说道:

    Thank you ever so for you article.Much thanks again. Want more.

  101. have a look at说道:

    It as wonderful that you are getting ideas from this article as well as from our discussion made here.

  102. you are saying and the way in which during which you say it.

  103. magnificent points altogether, you just gained a brand new reader. What would you recommend about your post that you made some days ago? Any positive?

  104. new reader. What could you recommend in regards

  105. Just Browsing While I was surfing today I saw a great article about

  106. Really clear website , thankyou for this post.

  107. post说道:

    Wow! This could be one particular of the most helpful blogs We have ever arrive across on this subject. Basically Magnificent. I am also a specialist in this topic so I can understand your hard work.

  108. Nnamdi说道:

    Really enjoyed this blog article.Thanks Again. Keep writing.

  109. themselves, particularly thinking about the fact that you simply could possibly have performed it if you ever decided. The pointers at the same time served to supply an incredible method to

  110. premium ads说道:

    Really appreciate you sharing this blog article.Really thank you! Keep writing.

  111. in that case, because it is the best for the lender to offset the risk involved

  112. browse说道:

    Please keep us informed like this. Thanks for sharing.

  113. These are generally probably the most awesome and fashion chanel bags I ave actually had. And really fashionable. Worth every single cent.

  114. This blog is without a doubt awesome and diverting. I have picked a lot of handy stuff out of this blog. I ad love to come back again soon. Cheers!

  115. link说道:

    Thanks for the post.Really thank you! Great.

  116. Very neat blog article.Much thanks again. Much obliged.

  117. wow, awesome article.Really looking forward to read more. Really Great.

  118. hoa don dien tu说道:

    This is my first time visit at here and i am genuinely impressed to read all at one place.

  119. Wow, that as what I was searching for, what a stuff! existing here at this website, thanks admin of this site.

  120. official site说道:

    It’а†s really a great and helpful piece of information. I’а†m satisfied that you just shared this useful information with us. Please stay us informed like this. Thanks for sharing.

  121. go there说道:

    You are my inspiration, I have few blogs and often run out from post . Analyzing humor is like dissecting a frog. Few people are interested and the frog dies of it. by E. B. White.

  122. Yes, you are right buddy, daily updating web site is genuinely needed in favor of Web optimization. Good argument keeps it up.

  123. Micah说道:

    I think other website proprietors should take this web site as an model, very clean and excellent user genial style and design, as well as the content. You are an expert in this topic!

  124. orlando seo说道:

    Usually I do not read post on blogs, however I wish to say that this write-up very compelled me to take a look at and do it! Your writing style has been surprised me. Thank you, very great post.

  125. This particular blog is really entertaining additionally factual. I have found a lot of useful tips out of this source. I ad love to go back again soon. Thanks a bunch!

  126. genuine parts说道:

    out. I like what I see so now i am following you.

  127. click here说道:

    Really informative post.Thanks Again. Awesome.

  128. Your style is unique in comparison to other folks I ave read stuff from. Thank you for posting when you ave got the opportunity, Guess I all just bookmark this web site.

  129. Keep up the superb work , I read few posts on this web site and I conceive that your web blog is rattling interesting and contains bands of great information.

  130. Looking forward to reading more. Great blog post.Thanks Again. Awesome.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>