The goal is to add N new elements to the DOM as quickly and as painlessly as possible.
I have access to jQuery and found the code below to be faster than the following:
$(parentElement)
.append(Array(1001).join(template))
;
var | |
fragment = document.createDocumentFragment() | |
,div = document.createElement('div') | |
,temp = '<div class="foo"><a href=#">bar</a><span class="catpants">baz</span></div>' | |
; | |
div.innerHTML = Array(1001).join(temp); | |
while (temp = div.firstChild) { | |
fragment.appendChild(temp); | |
} | |
parentElement.appendChild(fragment); |
also ... if nodes inside parentElement are less than node to insert ... maybe it makes sense to hold them, use innerHTML, and place them again through fragment
var tmp, fragment = document.createDocumentFragment();
while (tmp = parentElement.firstChild) fragment.appendChild(tmp);
parentElement.innerHTML = Array(1001).join(template);
parentElement.insertBefore(fragment, parentElement.firstChild);
latter idea/hint requires a bench in any case ;)
I'm appending to the parentElement
. I can''t innerHTML
it without +=
. The 1000 number is arbitrary and on the high end of normal use. In most cases, there will be 50 elements before the placeholder elements. I'll look into the 2nd solution. I like the idea.
Yes fragments + cloneNode() is always faster than innerHTML, at least that's what I tested long ago.
Take this as a start:
window.onload = function() {
var i = 0, start, end, tmp, fragment = document.createDocumentFragment(),
temp = '<div class="foo"><a href=#">bar</a><span class="catpants">baz</span></div>',
div = document.createElement('div'),
parentElement = document.body;
start = new Date().getTime();
div.innerHTML = temp;
tmp = div.firstChild;
while (1000 > i++) fragment.appendChild(temp.cloneNode(true));
parentElement.appendChild(fragment);
end = new Date().getTime();
console.log(end - start);
}
tested on Chrome/Opera to be almost 2x faster, and on Firefox/Safari still faster but not that much.
A typo in the previous snippet, should be:
while (1000 > i++) fragment.appendChild(tmp.cloneNode(true));
You might wanna take the performance testing to jsPerf, guys ;)
Very nice gentlemen. I have a few ideas to test now. Thanks a lot.
Here is my jsPerf test:
http://jsperf.com/dom-fragments-and-clonenode-vs-fragments-and-innerhtml
if parentElement is empty, !parentElement.firstChild, you can skip the loop and use innerHTML directly so that
parentElement.innerHTML = Array(1001).join(temp);
So, basically, you miss an if that checks if nothing is there, inject directly ... otherwise the technique seems to be a good one, imho