How to handle initializing and rendering subviews in Backbone.js?

I have three different ways to initialize and render a view and its subviews, and each one of them has different problems. I’m curious to know if there is a better way that solves all of the problems:


Scenario One:

Initialize the children in the parent’s initialize function. This way, not everything gets stuck in render so that there is less blocking on rendering.

initialize : function () {

    //parent init stuff

    this.child = new Child();
},

render : function () {

    this.$el.html(this.template());

    this.child.render().appendTo(this.$('.container-placeholder');
}

The problems:

  • The biggest problem is that calling render on the parent for a second time will remove all of the childs event bindings. (This is because of how jQuery’s $.html() works.) This could be mitigated by calling this.child.delegateEvents().render().appendTo(this.$el); instead, but then the first, and the most often case, you’re doing more work unnecessarily.

  • By appending the children, you force the render function to have knowledge of the parents DOM structure so that you get the ordering you want. Which means changing a template might require updating a view’s render function.


Scenario Two:

Initialize the children in the parent’s initialize() still, but instead of appending, use setElement().delegateEvents() to set the child to an element in the parents template.

initialize : function () {

    //parent init stuff

    this.child = new Child();
},

render : function () {

    this.$el.html(this.template());

    this.child.setElement(this.$('.placeholder-element')).delegateEvents().render();
}

Problems:

  • This makes the delegateEvents() necessary now, which is a slight negative over it only being necessary on subsequent calls in the first scenario.

Scenario Three:

Initialize the children in the parent’s render() method instead.

initialize : function () {

    //parent init stuff
},

render : function () {

    this.$el.html(this.template());

    this.child = new Child();

    this.child.appendTo($.('.container-placeholder').render();
}

Problems:

  • This means that the render function now has to be tied down with all of the initialization logic as well.

  • If I edit the state of one of the child views, and then call render on the parent, a completely new child will be made and all of its current state will be lost. Which also seems like it could get dicey for memory leaks.


Really curious to get your guys’ take on this. Which scenario would you use? or is there a fourth magical one that solves all of these problems?

Have you ever kept track of a rendered state for a View? Say a renderedBefore flag? Seems really janky.

7 Answers
7

Leave a Comment