jQuery appending an array of elements
JavascriptJqueryArraysPerformanceAppendJavascript Problem Overview
For the purpose of this question lets say we need to append()
1000 objects to the body
element.
You could go about it like this:
for(x = 0; x < 1000; x++) {
var element = $('<div>'+x+'</div>');
$('body').append(element);
}
This works, however it seems inefficient to me as AFAIK this will cause 1000 document reflows. A better solution would be:
var elements = [];
for(x = 0; x < 1000; x++) {
var element = $('<div>'+x+'</div>');
elements.push(element);
}
$('body').append(elements);
However this is not an ideal world and this throws an error Could not convert JavaScript argument arg 0 [nsIDOMDocumentFragment.appendChild]
. I understand that append()
can't handle arrays.
How would I using jQuery
(I know about the DocumentFragment node, but assume I need to use other jQuery functions on the element such as .css()
) add a bunch of objects to the DOM at once to improve performance?
Javascript Solutions
Solution 1 - Javascript
You could use an empty jQuery object instead of an array:
var elements = $();
for(x = 0; x < 1000; x++) {
elements = elements.add('<div>'+x+'</div>');
// or
// var element = $('<div>'+x+'</div>');
// elements = elements.add(element);
}
$('body').append(elements);
This might be useful if you want to do stuff with newly generated element inside the loop. But note that this will create a huge internal stack of elements (inside the jQuery object).
It seems though that your code works perfectly fine with jQuery 1.8.
Solution 2 - Javascript
You could just call
$('body').append(elements.join(''));
Or you can just create a large string in the first place.
var elements = '';
for(x = 0; x < 1000; x++) {
elements = elements + '<div>'+x+'</div>';
}
$(document.body).append(elements);
Like you mentioned, probably the most "correct" way is the usage of a DocFrag. This could look like
var elements = document.createDocumentFragment(),
newDiv;
for(x = 0; x < 1000; x++) {
newDiv = document.createElement('div');
newDiv.textContent = x;
elements.append( newDiv );
}
$(document.body).append(elements);
.textContent
is not supported by IE<9 and would need an conditional check to use .innerText
or .text
instead.
Solution 3 - Javascript
Upgrade to jQuery 1.8, this works as intended:
$('body').append([ '<b>1</b>', '<i>2</i>' ]);
Solution 4 - Javascript
Since $.fn.append takes a variable number of elements we can use apply
to pass the array as arguments to it:
el.append.apply(el, myArray);
This works if you have an array of jQuery objects. According to the spec though you can append an array of elements if you have the DOM elements. If you have an array of html strings you can just .join('') them and append them all at once.
Solution 5 - Javascript
A slight change to your second approach:
var elements = [],
newDiv;
for (x = 0; x < 1000; x++) {
newDiv = $('<div/>').text(x);
elements.push(newDiv);
}
$('body').append(elements);
$.append() certainly can append an array: http://api.jquery.com/append/
> .append(content) | content: One or more additional DOM elements, arrays of elements, HTML strings, or jQuery objects to insert at the end of each element in the set of matched elements.
Solution 6 - Javascript
Sometimes, jQuery isn't the best solution. If you have a lot of elements to append to the DOM, documentFragment
is a viable solution:
var fragment = document.createDocumentFragment();
for(var i = 0; i < 1000; i++) {
fragment.appendChild(document.createElement('div'));
}
document.getElementsByTagName('body')[0].appendChild(fragment);
Solution 7 - Javascript
If you're going for raw performance then I would suggest pure JS, though some would argue that your development performance is more important than your site's/program performance. Check this link for benchmarks and a showcase of different DOM insertion techniques.
edit:
As a curiosity, documentFragment
proves to be one of the slowest methods.
Solution 8 - Javascript
I would use native Javascript, normally much faster:
var el = document.getElementById('the_container_id');
var aux;
for(x = 0; x < 1000; x++) {
aux = document.createElement('div');
aux.innerHTML = x;
el.appendChild(aux);
}
EDIT:
There you go a jsfiddle with different options implemented. The @jackwander's solution is, clearly, the most effective one.
Solution 9 - Javascript
I know, the question is old, but maybe it helps others.
Or simple use ECMA6 spread operator:
$('body').append(...elements);