Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to generate html dynamically with jQuery

Tags:

I found some different and conflicting answers on this topic.

I am building an application which works mostly with html dynamically generated by jQuery, based on results acquired from underlying API in form of JSON data.

I was told by some of my collegues (personally), that the best way would be to do something like this:

var ul = $("<ul>").addClass("some-ul");
$.each(results, function(index) {
  ul.append($("<li>").html(this).attr("id", index));
});
$("body").append($("<div>").attr("id", "div-id").addClass("some-div").append(ul));

etc. The reason I was told it was that "updates the DOM directly instead of parsing html to achieve it".

However, I see lots of code like this (same example):

var toAppend = '<div class="some-div" id="div-id"><ul>';
$.each(results, function(index) {
  toAppend += '<li id="' + index + '">' + this + '</li>';
});
toAppend += '</ul></div>'

Which I personally consider as not as elegant - but is it better? I googled the issue for a couple of minutes and found this article. Basically, it is about increasing performance drastically by using string concatenation - my "second way".

The main issue of this article is that it has been released in 2009 and discussed jQuery version is 1.3. Today, the current release is version 1.6.4 which can behave quite differently. And this is the issue of most articles on the subject I have already found and I'm also somehow suspicious about their credibility.

That's why I have decided to post the question here and ask - which method of generating DOM is actually the proper one, based on performance?

IMPORTANT EDIT:

I have written a little benchmark to test which approach is better considering performance.

jsFiddle - concatenation version

jsFiddle - array join version

Code:

var text = "lorem ipsum";
var strings = $("#strings");
var objects = $("#objects");
var results = $("#results");

// string concatenation
var start = new Date().getTime();
var toAppend = ['<div class="div-class" id="div-id1"><ul class="ul-class" id="ul-id1">'];
for (var i = 1; i <= 20000; i++) {
    toAppend[i] = '<li class="li-class" id="li-id1-' + i + '">' + text + '</li>';
}
toAppend[i++] = '</ul></div>';
results.append(toAppend.join(""));
strings.html(new Date().getTime() - start);

// jquery objects
var start = new Date().getTime();
var ul = $("<ul>").attr("id", "ul-id2").addClass("ul-class");
for (var i = 0; i < 20000; i++) {
    ul.append($("<li>").attr("id", "li-id2-" + i).addClass("li-class"));
}
results.append($("<div>").attr("id", "div-id2").addClass("div-class").append(ul));
objects.html(new Date().getTime() - start);

It seems that operating on strings is faster (in Firefox 7 about 7 times) than using jQuery objects and methods. But I can be wrong, especially if there are any mistakes or performance-decreasing bugs in this "benchmark's" code. Feel free to make any changes.

Note: I used Array join because of the article mentioned earlier instead of actual concatenation.

EDIT: Based on suggestion by @hradac, I used actual string concatenation in the benchmark and it did in fact improve the times.

like image 664
Przemek Avatar asked Oct 07 '11 11:10

Przemek


People also ask

How can make HTML control dynamically using jQuery?

Create Dynamic Controlsappend() event with the control in which you want to add some dynamic controls and in that append event you need to write the HTML code similar to what you might have written in the body section and this will work for you, for example: <script> $(document). ready(function () {

What is the most efficient way to create HTML elements using jQuery?

Conclusion: The $(document. createElement('div')); is the fastest method, even the benchmarking supports, this is the fastest technique to create an HTML element using jQuery.

How can show dynamic data in jQuery?

jQuery Example to Load ListBox DynamicallyCreate UI to be appended for each user information. Download and import latest version of jQuery library files and jQuery UI files. Create custom jQuery handlers to append UI and load dynamic data into it. Trigger handlers on the mouse click event of Add User icon.


2 Answers

First of all, this kind of micro-benchmarking almost never tells you what you want to really know. Second of all, your benchmarks are varied and not equivalent. For example, your first example generates lines that look like this:

<li class="li-class" id="li-id1-493">lorem ipsum</li>

and your second lines like this:

<li id="li-id2-0" class="li-class"></li>

Notice the different element order and the lack of "lorem ipsum" text. Nor is there any attempt to clean out the results div between tests to avoid performance issues as a result of the first 20K results already being there.

But beyond these issues is the question, "Is performance on this really disrupting the client side user experience?" Seriously? You're rendering such a quantity of text this way that you're seeing noticeable differences between the alternative methods rendering the text?

I'll harken back to what others have said, use a templating engine. The fastest ones are quite quick indeed and even have pre-compilation options to allow you to re-render the same template and get quick results. So don't believe me. Instead, believe a demonstration. Here's my jsFiddle to demonstrate the performance of the new JsRender library that is supposed to replace the jQuery Template engine...

http://jsfiddle.net/LZLWM/10/

Note: It can take several seconds for JsRender to load into the Fiddle. It's because I'm pulling it straight out of GitHub and that's not something that GitHub is particularly good at. I don't recommend that in actual practice. It doesn't change the timings though and it's necessary until jsFiddle starts incorporating templating engines as options.

Notice that the second example, much closer to a real-world example generates 20,000 lines using JSON as its starting point in time approximately the same as your fastest test (< 50ms difference on my machine). Note also that both the code and the template are much clearer and easier to work with than any mess of appends and string concatenation is ever going to be. How many iterations am I going to need to get my template right vs. what you're doing?

Use something simple and stop wasting time on this level of micro optimization when it's probably not even necessary. Instead use templates like this (or any of several other good templating engines) and make sure that you've got expires headers turned on, you're using a CDN, you've got gzip compression turned on on your server, etc. All the stuff that YSlow is telling you to do, because that will completely swamp the effects of what you're looking at here.

like image 157
John Munsch Avatar answered Oct 04 '22 20:10

John Munsch


Check out jquery templates -

http://api.jquery.com/category/plugins/templates/

like image 34
John Strickler Avatar answered Oct 04 '22 19:10

John Strickler