Backbone.js:通过模板嵌套视图

时间:2011-08-18 19:32:23

标签: javascript jquery backbone.js templating

技术上是否可以使用模板来嵌套视图:

<%= new PhotoCollectionView({model:new PhotoCollection(model.similarPhotos)}).render().el) %>

我也可以将所有内容都放在渲染方法中,但模板为灵活性和布局提供了更多空间。

我尝试了上述变体,但我在屏幕上得到的结果是[HTMLDivElement]

如果我尝试仅提取HTML,使用jQuery的HTML,我会将其渲染,但事实证明,打印出来的DOM节点与视图引用的DOM节点不同,因为使用视图实例,无法与这些DOM节点进行任何交互。例如,如果在视图中我说$(this.el).hide(),则不会发生任何事情。

什么是正确的方法,如果有的话?

5 个答案:

答案 0 :(得分:29)

我通常首先渲染父视图。然后我使用this.$('selector')方法查找一个可以用作子视图el的子元素。

以下是一个完整的例子:

var ChildView = Backbone.View.extend({
  //..
})

var ParentView = Backbone.View.extend({
  template: _.template($('#parent-template').html()),
  initialize: function() {
    _.bindAll(this, 'render');
  }
  render: function() {
    var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
    return this;
  }
});

var v = new ParentView();
v.render(); 

答案 1 :(得分:14)

接受的答案有一个重大缺陷,即每次渲染时都会重新初始化ChildView。这意味着您将丢失状态,并且可能必须在每个渲染上重新初始化复杂视图。

我在这里写了一篇博客:http://codehustler.org/blog/rendering-nested-views-backbone-js/

总结一下,我建议使用这样的东西:

var BaseView = Backbone.View.extend({

    // Other code here...

    renderNested: function( view, selector ) {
        var $element = ( selector instanceof $ ) ? selector : this.$el.find( selector );
        view.setElement( $element ).render();
    }
});

var CustomView = BaseView.extend({

    // Other code here...

    render: function() {
        this.$el.html( this.template() );
        this.renderNested( this.nestedView, ".selector" );
        return this;
    }
});

如果你不想扩展Backbone视图,可以将renderNested方法放在你喜欢的任何地方。

使用上面的代码,您现在可以在初始化方法中初始化ChildView,然后在调用render()时简单地渲染它。

答案 2 :(得分:2)

查看Backbone.Subviews mixin。它是一个用于管理嵌套视图的极简主义mixin,并且不会在每次呈现父级时重新初始化子视图。

答案 3 :(得分:1)

我不知道模板本身,但我以前用表和列表完成了。在外部模板中,只有stub:

<script type="text/template" id="table-template">
    <table>
        <thead>
            <th>Column 1</th>
        </thead>
        <tbody>
        </tbody>
    </table>
</script>

以及个别项目:              &lt;%= field1%&gt;     

然后在你的渲染方法中,只渲染单个项目并将它们附加到tbody元素......

答案 4 :(得分:-1)

每次渲染时初始化一个新对象的决定在我看来效率很低。 特别是:

render: function() {
    var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
    return this;
  }

理想情况下,父级的渲染应该类似于

render: function() {
   this.$el.html(this.template());
   this.childView1.render();
   this.childView2.render();
}

只有在初始化父级时才会创建子级:

initialize: function() {
       this.childView1 = new ChildView1(selector1);
       this.childView2 = new ChildView2(selector2);
} 

问题是我们在渲染父模板之前没有selector1和selector2。这就是我现在陷入困境的地方:)