Backbone.js将子视图元素添加到父视图的元素

时间:2013-05-01 16:14:31

标签: javascript jquery backbone.js underscore.js

我有一个集合视图和一个模型视图,如下所示:

EventListView
|-- EventView

EventListView必须在一对多关系中显示多个EventViews。我使用下划线_.template()函数来构建我的视图模板。

以下是我的EventView模板:

<h1>
    <span class="date"><%= prefix %><%= dateString %></span>
    <span class="title"><%= title %></span>
</h1>
<div class="caption"><%= caption %></div>

我的EventView渲染方法:

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

这是我的EventListView模板:

<h1>
    <% if(typeof(title) != "undefined") { print(title) } %>
</h1>
<%= events %>

这是渲染方法:

// this._EventViews is an array of eventView objects
render: function() {

    var templateData = {
        events: _.reduce(this._EventViews, function(memo, eventView) { return memo + eventView.$el.html(); }, "")
    }
    this.$el.html(this.template(templateData));
    return this;
}

我遇到的问题是eventView.$el.html()仅包含模板中的HTML,但我需要利用tagNameclassNameid属性骨干视图支持。

考虑我是否如此设置EventView

return Backbone.View.extend({

    model: EventModel
,   tagName: 'article'
,   className: 'event'  
,   template: _.template(templateText)

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

我想插入:

<article class="event" id="someID342">
    <h1>
       <span class="date">01/02/2010</span>
       <span class="title"></span>
       <div class="caption></div>
    </h1>
</article>

eventView.$el返回:

<h1>
   <span class="date">01/02/2010</span>
   <span class="title"></span>
   <div class="caption></div>
</h1>

如何插入整个eventView元素?不仅仅是innerHTML

3 个答案:

答案 0 :(得分:0)

render()函数不应负责处理view.el的设置。这是由初始化视图时调用的Backbone函数中的_ensureElement完成的。

此外,$.fn.html()函数仅应返回所选元素的内容。

答案 1 :(得分:0)

只需在EvenListView的模板中保留占位符

<h1><%- title %></h1>
<div class="js-events"></div>

然后渲染并附加子视图

render: function() {
    this.$el.html(this.template({title: 'Title'}));
    this.$events = this.$('.js-events');
    _.each(this._EventViews, function (eventView) {
        this.$events.append(eventView.render().$el);
    }, this);
    return this;
}

答案 2 :(得分:0)

您有很多选择,但我认为最灵活和可持续的方法是让每个子视图定义自己的模板。父视图只是附加子元素.el属性。

这种方法的优点是,您的模板只编译一次。对子项的更新不需要重新渲染父元素和邻近元素。

这是JSBin

实施例

var ContainerView = Backbone.View.extend({

  tagName: "article",
  className: "event",
  id: "someID342",

  initialize: function(options){
    //the template will now be rendered
    this.childView = new ChildView()

    //the rendered child will now appear within the parent view
    this.el.appendChild( this.childView.el )
  }

})

var ChildView = Backbone.View.extend({

  tagName: "h1",
  dateString:"01/02/2010",
  prefix: "Date: ",
  caption: "What a wonderful date!:",
  title: "I am a title",
  template: _.template([
    '<h1>',
      '<span class="date"><%= prefix %><%= dateString %></span>',
      '<span class="title"><%= title %></span>',
    '</h1>',
    '<div class="caption"><%= caption %></div>'
  ].join("")),

  initialize: function(){
    this.render()
  },

  render: function(){
    // because you are only altering innerHTML
    // you do not need to reappend the child in the parent view
    this.el.innerHTML = this.template(this)
  }

})

我个人提醒不要在Backbone中使用模板。我发现只需为应用程序的每个组件设置一个Backbone视图就可以更轻松地进行编辑。共享模板比共享视图困难得多。当然,这取决于您项目的要求。