4

I have a list of products, where I need to update the innerHTML of a #container dynamically.

My question is, if I do something like in this answer: Jquery Remove All Event Handlers Inside Element

$("#container").find("*").off();

So, I remove all the event handlers for all the children, and then I update the html:

$("#container").html(responseFromAJAX);

How will this affect on the performance? I mean, is this a good way, to remove all the old elements and handlers, and clean up memory, or I need to do more?

My app is a webshop, so my Users will look around, and update the #container maybe 30-50 times/visit.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
seniorpreacher
  • 666
  • 2
  • 11
  • 31
  • 1
    when you do the `html(responseFromAJAX)`, surely this will replace all the current html so you shouldn't need to remove all the handlers first – Pete Jan 20 '14 at 12:09
  • 1
    in that case you need to use [empty()](http://api.jquery.com/empty/) as it removes the event handlers are jQuery data – Arun P Johny Jan 20 '14 at 12:13
  • @Pete - removing something from the DOM does not automatically remove event handlers and data still present in memory. – adeneo Jan 20 '14 at 12:26
  • @adeneo when you use .html to replace the contents it does remove all the event handlers associated with the previous content – Pete Jan 20 '14 at 12:36
  • 1
    @Pete - It does, but only because jQuery cleans up the event handlers and the data, innerHTML would not do the same. Simply replacing the content is not enough. – adeneo Jan 20 '14 at 12:38
  • @adeneo I didn't comment on innerHtml – Pete Jan 20 '14 at 13:36
  • guys, maybe I made a confusion by writing innerHTML in the question. But now it's clear, that jQuery does a bit more, then just set the innerHTML, so this is a valuable information, what I needed, so thanks! ;) – seniorpreacher Jan 20 '14 at 16:04

2 Answers2

7

Event handlers, connected directly to DOM elements, die when the DOM elements are removed from the DOM.

Replacing the content is enough.

Delegated events as a better alternative:

The rules for deferred events (event delegation) are different, as the events are not actually connected to the individual DOM elements, but are captured at a higher level (like the document). A selector is then run and the event function run against the matching element(s). Deferred events tie up less memory but are a tiny(-tiny) bit slower to run (you will never notice the difference for mouse events) as the element search is only done when the event triggers.

I would generally recommend using deferred on, instead of connecting to lots of individual elements, especially when your DOM elements are loaded dynamically.

e.g.

$(document).on('someeventname', 'somejQueryselector', function(e){
    // Handle the event here
});

Sequence of events with a delegated handler

  • Attach a delegated handler to a single non-changing ancestor element (document is the best default for several reasons if nothing else is closer/convenient). See notes for details.
  • The chosen event bubbles up to the delegated target element
  • The jQuery selector is applied to just the elements in the bubble-chain
  • The event handler is run against only the matching elements that caused the event.

The upshot of this is that delegated handlers only match at event time, so can cope with dynamically added/removed content. The runtime overhead is actually lower at event registration (as it only connects to a single element) and the speed difference at event time is negligible (unless you can click a mouse 50,000 times per second!).

Notes:

  • With delegated events, you should try to attach them to a single element, that is an ancestor of the target elements and that will not change.
  • The fallbacks are usually body or document if nothing else is handy.
  • Using body for delegated events can cause a bug to do with styling. This can mean mouse events do not bubble to body (if the computed height of body is 0). document is safer as it is not affected by styling.
  • Also document always exists, so you can attached delegated event handlers outside of a DOM-ready handler with no problems.
iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
  • This answer doesn't explain *how* to use delegated events. Are jQuery events delegated? –  Apr 20 '16 at 12:18
  • 2
    @buffjape: Added an example of using a delegated event on `document`. As to your question, only delegated jQuery events are delegated (not the event handlers that have no selector as the second parameter) :) – iCollect.it Ltd Apr 20 '16 at 14:33
4

You can just use html(), like many of the other jQuery methods, it cleans up the event handlers and the associated data (which btw is not automatically cleaned up when elements are removed from the DOM).

$("#container").html(responseFromAJAX);

From the documentation :

When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.

adeneo
  • 312,895
  • 29
  • 395
  • 388