嵌套在另一个模板中的骨架模板

8
有没有可能在模板中嵌套另一个模板并通过backbone视图访问呢?
例如,我有View1使用Template1,View2使用Template2。实际上,Template2需要在Template1的DIV中。我将Template2 DIV容器放置在Template1中并附上适当的ID,但渲染页面时它不会显示。如果我从Template1内部删除Template2 div容器,只是将它放在页面主体中,它就可以正常工作。
所以我想知道这是否可能,或者必须嵌套视图/模型等才能使其工作?
Template2中的数据与Template1无关,只需在页面上嵌入Template1中的位置显示即可。

你能分享一些代码吗? - u.k
我知道这并不是你问题的答案,但Ember js支持接近这个功能。你可以定义嵌套资源...这样就可以在模板中嵌套模板了。http://emberjs.com/guides/routing/defining-your-routes/ - Jaspreet Singh Lidder
5个回答

21

我过去处理这个问题的方式是分别定义这两个视图,然后当你渲染View1时,创建一个新的View2,将其渲染并插入到View1中。所以:

window.View1 = Backbone.View.extend({
    render: function() {
        this.view2 = new View2();
        this.$('insert-view-here').append(this.view2.render().el);
    }
});

1
在这种情况下,您如何处理内部元素的更改?您总是从上到下呈现,还是内部元素可以以某种方式自行更改? - Rob Fox
对内部元素的更改可以由第二个视图处理,就像在任何其他情况下一样处理它们。如果由于某种原因父视图或模型发生更改并需要重新呈现HTML,则子视图将在此呈现方法中重新创建。 - RTigger

4

你应该为此创建子视图。

我喜欢在闭包中私有化子视图并返回公共视图。

var View = (function (BV) {
    var View, Subview;

    // Only this main view knows of this subview
    Subview = BV.extend({ 
        template: _.template( subtmpl ),

        render: function () {
            this.$el.html( this.template( this.model.toJSON() ) );
            return this;
        }   
    }); 

    View = BV.extend({
        template: _.template( tmpl ),

        render: function () {
            this.$el.html( this.template( this.model.toJSON() ) );

            var subview = new SubView({ model: this.model }); 

            // replace a div in your template meant for teh subview with the real subview
            this.$el.find( "#subview" ).replaceWith( subview.render().el );

            return this;
        }   
    }); 

    return View;

}(Backbone.View));

var view = new View({ model: user });
var subview = new Subview; // Reference Error

2

当你需要在Template1中多次包含Template2时,比如说在<ul>标签内作为<li>元素的时候,另一个有用的选项是将Template2函数传递到Template1中。(摘自Rico Sta Cruz的Backbone Patterns。)

TasksList = Backbone.View.extend({
  // Template1, inlined in js.
  template: _.template([
    "<ul class='task_list'>",
      "<% items.each(function(item) { %>",
        "<%= itemTemplate(item) %>",
      "<% }); %>",
    "</ul>"
  ].join('')),

  // Template2, inlined in js.
  itemTemplate: _.template(
    "<li><%= name %></li>"
  ),

  render: function() {
    var html = this.template({
      items: tasks /* a collection */,
      itemTemplate: this.itemTemplate
    });

    $(this.el).append(html);
  }
});

0
一个更加简洁的方案是不需要使用jQuery的append()方法或者添加额外的子视图对象,而是可以使用underscore的渲染/编译方法预先处理,并将子视图作为字符串插入到主模板中,使用内部注释标记。这样可以避免在双重的jQuery范围内进行操作。
View = Backbone.View.extend({
  template: _.template(...),
  prerender: function(tpl,model){// pre-render a component
      var template = _.template(tpl);
      return template(model);
  },
  render: function(){
    var model = { ... };
    var component = this.prerender(this.itemTemplate, model);
    this.$el.html(this.template(model).replace('<!--#component-->', component));
  }
});

如果你的模板不是一个常量,而是依赖于当前作用域的某个属性,这会非常有用。

请注意,在本问题的范围内,您需要将View2模型传递给组件。


0

我理解的典型方式是将视图视为可以嵌套在彼此中的完整对象。假设您有两个视图,ViewA和ViewB。以下代码显示了如何将ViewB附加到ViewA中。

# this is coffeescript, but it's easily translated to JS
class ViewA extends Backbone.View
    initialize: () ->
        this.render()

    render: ()->
        this.$el.append(new ViewB().$el)
        this.$el.append(new ViewB().$el)
        return this

你可以在管理ViewB时变得更加高级(将其分配给属性或其他方式),或者为每个ViewB实例传递不同的构造函数参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接