Backbone.js : subviews rendering

JavaScript performance comparison

Test case created by nikoshr

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//documentcloud.github.com/underscore/underscore-min.js"></script>
<script src="//documentcloud.github.com/backbone/backbone-min.js"></script>

<div id='rendered'>
</div>



<script id="tpl1-table" type="text/template">
    <table>
        <caption><%= caption %></caption>
        <thead>
            <tr>
                <th>Row</th>                
                <th>Name</th>
            </tr>
        </thead>
     </table>
</script>
<script id="tpl1-row" type="text/template">
    <tr>
        <td><%= row %></td>                
        <td><%= name %></td>
    </tr>
</script>

<script id="tpl2-table" type="text/template">
    <table>
        <caption><%= caption %></caption>
        <thead>
            <tr>
                <th>Row</th>                
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
        <% _(children).each(function(model) { %>
            <tr id='<%= model.cid %>'>
                <td><%= model.row %></td>
                <td><%= model.name %></td>
            </tr>
        <% }); %>
        </tbody>
     </table>
</script>

<script id="tpl3-table" type="text/template">
    <table>
        <caption><%= caption %></caption>
        <thead>
            <tr>
                <th>Row</th>                
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
        <% _(children).each(function(model) {
            print( subtemplate(model) );
        }); %>
        </tbody>
     </table>
</script>

<script id="tpl3-row" type="text/template">
    <tr id='<%= cid %>'>
        <td><%= row %></td>                
        <td><%= name %></td>
    </tr>
</script>

<script id="tpl4-table" type="text/template">

    <table>
        <caption><%= collection.caption %></caption>
        <thead>
            <tr>
                <th>Row</th>                
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
        <% _(collection.children).each(function(model) {
            print( collection.subtemplate(model) );
        }); %>
        </tbody>
     </table>
</script>

<script id="tpl4-row" type="text/template">
    <tr id='<%= model.cid %>'>
        <td><%= model.row %></td>                
        <td><%= model.name %></td>
    </tr>
</script>
 
<script>
Benchmark.prototype.setup = function() {
    var data = [];
    for (var i = 0; i < 100; i++) {
      data.push({
        row: i,
        name: "Row " + i
      });
    }
   
    var coll = new Backbone.Collection(data);
   
    var ItemView = Backbone.View.extend({
      events: {
        "click td": "show"
      },
      show: function() {
        console.log(this.model.get("name"));
      }
    });
   
   
    var Test1ItemView = ItemView.extend({
      template: _.template($('#tpl1-row').html()),
   
      render: function() {
        var html = this.template(this.model.toJSON());
        this.setElement($(html));
        return this;
      }
    });
   
    var Test1ListView = Backbone.View.extend({
      template: _.template($('#tpl1-table').html()),
   
      render: function() {
        var html = this.template({
          caption: "Test 1"
        });
        var $table = $(html);
   
        this.collection.each(function(model) {
          var view = new Test1ItemView({
            model: model
          });
          var $tr = view.render().$el;
          $table.append($tr);
        });
   
        this.$el.empty();
        this.$el.append($table);
   
        return this;
      }
    });
   
   
    var Test2ListView = Backbone.View.extend({
      template: _.template($('#tpl2-table').html()),
   
      render: function() {
        var data = this.collection.map(function(model) {
          return _.extend(model.toJSON(), {
            cid: model.cid
          });
        });
        var html = this.template({
          children: data,
          caption: "Test 2"
        });
        var $table = $(html);
   
        this.collection.each(function(model) {
          new ItemView({
            el: $table.find("#" + model.cid),
            model: model
          });
        })
   
        this.$el.empty();
        this.$el.append($table);
   
        return this;
      }
    });
   
    var Test3ListView = Backbone.View.extend({
      template: _.template($('#tpl3-table').html()),
      subtemplate: _.template($('#tpl3-row').html()),
   
      render: function() {
   
        var data = this.collection.map(function(model) {
          return _.extend(model.toJSON(), {
            cid: model.cid
          });
        });
        var html = this.template({
          children: data,
          subtemplate: this.subtemplate,
          caption: "Test 3"
        });
        var $table = $(html);
   
        this.collection.each(function(model) {
          new ItemView({
            el: $table.find("#" + model.cid),
            model: model
          });
        });
   
        this.$el.empty();
        this.$el.append($table);
   
        return this;
      }
    });
   
    var Test4ListView = Backbone.View.extend({
      template: _.template($('#tpl4-table').html(), null, {
        variable: 'collection'
      }),
      subtemplate: _.template($('#tpl4-row').html(), null, {
        variable: 'model'
      }),
   
      render: function() {
   
        var data = this.collection.map(function(model) {
          return _.extend(model.toJSON(), {
            cid: model.cid
          });
        });
        var html = this.template({
          children: data,
          subtemplate: this.subtemplate,
          caption: "Test 4"
        });
        var $table = $(html);
   
        this.collection.each(function(model) {
          new ItemView({
            el: $table.find("#" + model.cid),
            model: model
          });
        });
   
        this.$el.empty();
        this.$el.append($table);
   
        return this;
      }
    });
   
   
   
   
   
    var view1 = new Test1ListView({
      collection: coll
    });
    $("#rendered").append(view1.el);
   
    var view2 = new Test2ListView({
      collection: coll
    });
    $("#rendered").append(view2.el);
   
    var view3 = new Test3ListView({
      collection: coll
    });
    $("#rendered").append(view3.el);
   
    var view4 = new Test4ListView({
      collection: coll
    });
    $("#rendered").append(view4.el);
};

Benchmark.prototype.teardown = function() {
    $("#rendered").empty();
};
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Render subview and append
view1.render();
pending…
Unique template
view2.render();
pending…
Compiled subtemplate, variable not set
view3.render();
pending…
Compiled subtemplate, variable set
view4.render();
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment