mc9
mc9

Reputation: 6341

Why is detaching and appending more efficient than changing html directly?

I was told that when inserting multiple elements into the DOM, it is more efficient to first detach the destination element, insert the elements, and then append it back to the DOM. I would like to know why.

For instance,

html

<div id="main">
  <ul class="list"></ul>
</div>

jQuery

var arrayOfElements = [$("<li> .... </li>"), $("<li> .... </li>"), ... , $("<li> ... </li>")]

# Appraoch 1
$(".list").html(arrayOfElements);

# Approach 2
$(".list").detach().html(arrayOfElements).appendTo(".main");

Why is appraoch 2 more efficient, and by how much significance?

Upvotes: 3

Views: 1002

Answers (1)

robbmj
robbmj

Reputation: 16526

When appending a series of elements to the DOM each triggers the browser to reflow the page. Adding one element to the page that has already been prepared while not on the DOM then appending that to the DOM only causes one reflow of the page.

From: http://www-archive.mozilla.org/newlayout/doc/reflow.html

All reflows have a reason, which is maintained in the reflow state object (and may mutate, as described below). The reflow reason controls how a frame reacts during a reflow, and is one of the following:

The article goes on to list the reasons for a reflow, the following is one such reason:

Incremental, when something in the frame tree changes; for example, when more content is read from the network, or some script manipulates the DOM. An incremental reflow is targeted at a single frame in the frame hierarchy. During an incremental reflow, a frame can assume that none of the constraints computed from above'' (for example, available width) have changed; instead, somethingwithin'' the frame has changed, which may have bottom-up impact to the frame hierarchy.

As for performance improvements I will leave that to John Resig.

Browser         Normal (ms) Fragment (ms)
Firefox 3.0.1   90          47
Safari  3.1.2   156         44
Opera 9.51      208         95
IE 6            401         140
IE 7            230         61
IE 8b1          120         40

Source: http://ejohn.org/blog/dom-documentfragments/

Your examples are somewhat flawed though.

var arrayOfElements = [$("<li>....</li>"), $("<li>....</li>"), $("<li>...</li>")];

Should be written as:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"].join('');

Secondly

// Approach 1
$(".list").html(arrayOfElements);

Between the two examples this one MAY actually be better. Why?

Because:

// Approach 2
$(".list").detach().html(arrayOfElements).appendTo("#main");

Can cause up to (and probably will) 2 reflows. Once when the <ul> is removed from the DOM and once when it is appended to the DOM. Approach 1 may cause 2 (or more) reflows, as .html will have to remove the current children and then append the second set. The determining factor will be if the .html method appends each element sequentially or all at once as one DOM element. But at very least it is easier to grok. And at best it removes one less element from the DOM potentially diminishing the effects of the reflow.

However both methods are preferable to the following:

var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"];
$('.list').children().remove();
for (var i = 0; i < arrayOfElements.length; i++) {
    $(arrayOfElements[i]).appendTo('.list');
}

Upvotes: 5

Related Questions