Why is disabling and adding more efficient than changing the 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 add it back to the DOM. I would like to know why.
For example,
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 score 2 more effective and how significant?
source to share
When a series of elements are added to the DOM, each will activate the browser to refresh the page. Adding one element to a page that has already been provisioned, not in the DOM, and then adding that parameter to the DOM only causes the page to be billed.
From: http://www-archive.mozilla.org/newlayout/doc/reflow.html
All recalculations have a cause that persists in the overflow state of the object (and can mutate, as described below). The reflow reason controls how the frame reacts during reflow and is one of the following:
The article lists the reasons for the redevelopment, the following reason:
Incremental when something in the frame tree changes; for example when more content is read from the web, or some script manipulates the DOM. Incremental toggle targets one frame in the frame hierarchy. During an incremental recalculation, a frame may assume that none of the constraints calculated
from above'' (for example, available width) have changed; instead, something
internally by '' have changed, which may have a bottom-up impact on the frame hierarchy.
As for the performance improvement, I'll 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 MAY will actually be better. Why?
Because:
// Approach 2
$(".list").detach().html(arrayOfElements).appendTo("#main");
Can cause up to (and probably will) 2 reflows. Once when it <ul>
is removed from the DOM and once when it is added to the DOM. Approach 1
may cause 2 (or more) reflows as you .html
have to remove the current children and then add a second set. The determining factor will be if the method .html
adds each element sequentially or at once as one DOM element. But at least it's easier to peek. And at best, it removes one smaller element from the DOM, potentially reducing the effects of re-melting.
However, both methods are preferred:
var arrayOfElements = ["<li>....</li>", "<li>....</li>", "<li>....</li>"];
$('.list').children().remove();
for (var i = 0; i < arrayOfElements.length; i++) {
$(arrayOfElements[i]).appendTo('.list');
}
source to share