Reputation: 7094
I am creating a jQuery mobile app where UI events generate lists on the fly. So the faster I can make these lists come up the more responsive my UI will appear. I've outlined a few approaches below. My hope is that people with expertise on web performance can either tell me which approach they think is best or suggest an entirely new approach.
Approach #1 "Programaticaly Generate
$.each(array, function(index, value){
var listElement = "$(<li></li>)";
listElement.text(array.elementName);
//Do some other stuff to listElement
$("#displayedList").append(listElement);
//append to Displayed List
});
Approach #2 "Clone
$.each(array, function(index, value){
var listElement = $("#listElementTemplate").clone();
//Cloned list element from already loaded dom element
listElement.text(array.elementName);
//Do some other stuff to listElement
$("#displayedList").append(listElement);
//append to Displayed List
});
Approach #3 "Display already loaded list in an iframe"
$("#displayedListWrapper").find("iframe").src("#loadedList");
Upvotes: 1
Views: 559
Reputation: 11381
Here's a jsPerf I made for your scenarios : http://jsperf.com/dynamic-li
Here's the sample JSON I used for this :
[
"Sweet Child 'O Mine",
"Summer of '69",
"Smoke in the Water",
"Enter Sandman",
"I thought I've seen everything",
"Never Hear Surf Music Again",
"The Canyon",
"Liberation Begins",
"Touch of the Sun",
"Lovely Day",
"Ca Plane Pour Moi",
"Liberation In A Dream",
"If You Love Me (Really Love Me)",
"Acid Darbari",
"R.I.P.",
"Festival",
"If I Rise",
"Liberation",
"Nocturne No. 2 in E flat"
]
And the test methods used are :
//Scenario #1 : Programmatically generate li elements
function makeLiProgrammatically() {
$.each(songs, function (i, song) {
var listElement = $("<li></li>");
listElement.text(song);
$list.append(listElement);
});
$list.listview("refresh");
}
//Scenario #2 : Clone DOM <li> element
function cloneDOMLi() {
$.each(songs, function (i, song) {
var listElement = $("#listElementTemplate").clone();
//Cloned list element from already loaded dom element
listElement.text(song);
//Do some other stuff to listElement
$list.append(listElement);
//append to Displayed List
});
$list.listview("refresh");
}
//Extra scenario - replacing each loop with for loop in scenario #1
function makeLiProgrammaticallyForLoop() {
for (; i < songs.length; i++) {
var listElement = $("<li></li>");
listElement.text(songs[i]);
$list.append(listElement);
};
$list.listview("refresh");
}
The last scenario is my addition, just to check if for
is better than each
in this scenario. And the results are.. drumroll
It looks like adding with <li>
programmatically,for
loop was the fastest! The reason, as Omar mentioned, is simple. You're creating an element in memory, so it doesnt consume that much of memory. Whereas, in your scenario #2, you were going to the DOM, searching for the - See EDITli
element (that too, repeatedly), which slowed it up.
Hope this clears things up!
PS Dont mind the screwed up formatting in jsPerf, I think jQM screwed it up when I added it to the scripts.
As Mathias pointed out, cloning a DOM object is the fastest! This is what I changed in scenario #2 :
//Scenario #2 : Clone DOM <li> element
function cloneDOMLi() {
var listElement = $("#listElementTemplate"); //pre cached the li so that it can be used again and again
$.each(songs, function (i, song) {
$list.append(listElement.clone().text(song));
});
$list.listview("refresh");
}
And added an extra scenario :
function cloneDOMLiForLoop() {
for(;i<songs.length; i++){
//Cloned list element from already loaded dom element
$listElement.clone().text(songs[i]);
//Do some other stuff to listElement
$list.append($listElement);
//append to Displayed List
};
}
It looks like caching the DOM li
did the trick! And as mentioned in the previous (wrong) observation, for
is faster than each
in this case as well. Results :
EDIT 1
I added one more test which creates <li></li>
only once, and clones it in the loop. And of course using for
loop. Here's the code :
function makeLiProgrammaticallyOnceForLoop() {
var li = $("<li></li>");
for(;i<songs.length; i++){
$list.append(li.clone().text(songs[i]));
};
$list.listview("refresh");
}
And here are the results :
Looks like programmatically creating li
and reusing it through clone
is also fast. So these would go without saying :
clone
. Use for
instead of each
if you want good performance.
Important I didnt mention i-frame approach in tests because for mobile phones, especially the ones running Android OS 2.3.7, there is a clunky implementation of i-frames in the native browser, its always good to avoid them, even though that might be the fastest one of your scenarios.
Upvotes: 1