Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js very slowly foreach

I'm trying to create a simple markup with templates. Something like:

<div class="list" data-bind="template: {name: 'mytemplate', data: someData}"></div>

<script id="mytemplate">
  <div class="item" data-bind="text: someText"></div>
</script>

It works very nice, but if i need to render a lot of divs with this templates its going to be very slow. Knockout after creating each div adds it to the document. But, if i do something like this:

el = document.createElement("div");
applyBindings(myModel, el);

(div.list).innerHTML = el.innerHTML

It works much faster but is inconvenient.

Maybe Knockout has some built in feature for creating a group of element and after that adding this group to the document?

like image 455
user1569318 Avatar asked Aug 01 '12 17:08

user1569318


2 Answers

It sounds like KO is manipulating the DOM with each DIV you add. DOM traversal is expensive and will slow down the rendering of your page. There is an open issue for this under the KO Github: https://github.com/SteveSanderson/knockout/issues/248

In my opinion, Knockout is presently not up to the task of handling large foreach data sets. Performance on Chrome is decent (because Chrome is awesome), but pretty bad on Internet Explorer (and even worse on older IE): http://jsfiddle.net/StarcounterJack/FgSCw/

Instead of using Knockout, try a manual approach: create the DIVs in memory first and insert them into the DOM all at once. This is what you're doing in your second example with document.createElement(). With jQuery, you could do this:

var newDiv = $("<div>my new div</div>");
var newDiv2 = $("<div>my new div2</div>");
newDiv.append(newDiv2);
$('body').append(newDiv); //only this last step traverses the DOM

For templating, I prefer to use Mustache.js, load the templates using John Resig's <head><script type="text/templates"> template inclusion trick and take care of the rendering manually through my own JavaScript. You have more control over how the elements are rendered and can try different approaches when you run into performance problems like the one you have now.

like image 50
Elliot B. Avatar answered Nov 05 '22 16:11

Elliot B.


The best solution right now might be my knockout-fast-foreach plugin.

It has O(1) inserts and deletes, among other features to make it notably fast (i.e. faster than one could easily do on your own).

It is a strong contender to replace the current foreach binding in KO 3.5 (or 3.6).

like image 21
Brian M. Hunt Avatar answered Nov 05 '22 16:11

Brian M. Hunt