如何使用 Marionette 的 ItemView 呈现集合?

How to render a collection with a Marionette's ItemView?

我正在尝试使用 Backbone.Marionette.ItemView 渲染来自 API (JSON) 的响应。不确定为什么它不起作用。

我正在使用 marionette v2.4.7(有意);

这是把手模板:

<script id="feed-post" type="text/x-handlebars-template">
  {{#each posts}}
    <a href="#"><img src="{{author.image_url}}" alt=""></a>
    <a href="#"><p>{{author.name}}</p></a>
    <span>TODO TIMESTAMP</span>
    <p>{{body}}</br>{{topic_type}}</p>
  {{/each}}
</script>

这是我的完整 app.js(此文件中的所有 Backbone 逻辑);

// Model
var Post = Backbone.Model.extend({
  defaults: {
    authorPic:      'Unknown',
    authorName:     'Unknown',
    timestamp:      'Unknown',
    body:           'Not available',
    comments:       '0'
  }
});

// Collection
var Posts = Backbone.Collection.extend({
  model: Post,
  url: 'http://localhost:4321/blogposts',
  initialize: function(){
    this.fetch();
  }
});

// View
var PostView = Marionette.ItemView.extend({
  el: '#content',
  template: Handlebars.compile($("#feed-post").html()),
});

//Config
var chunkPosts = new Posts();
var myview = new PostView({collection: chunkPosts});

此外,我尝试 console.log 视图,看起来模型在那里。

此答案专为 Marionette v2.4.7 量身定制。 LayoutViewItemViewv3.0.0 合并并重命名为 View


来自doc on ItemView

Rendering this view will convert the someCollection collection in to the items array for your template to use.

您在模板中使用 posts,而文档说它将被称为 items

作为参考,这里是 ItemView source 中执行此操作的确切代码:

// Serialize the model or collection for the view. If a model is
// found, the view's `serializeModel` is called. If a collection is found,
// each model in the collection is serialized by calling
// the view's `serializeCollection` and put into an `items` array in
// the resulting data. If both are found, defaults to the model.
// You can override the `serializeData` method in your own view definition,
// to provide custom serialization for your view's data.
serializeData: function() {
  if (!this.model && !this.collection) {
    return {};
  }

  var args = [this.model || this.collection];
  if (arguments.length) {
    args.push.apply(args, arguments);
  }

  if (this.model) {
    return this.serializeModel.apply(this, args);
  } else {
    return {
      items: this.serializeCollection.apply(this, args)
    };
  }
},

最后几行表明对于一个集合,返回一个以 items 作为唯一属性的新对象。

提到您可以覆盖 serializeData 函数,more information and examples are available in the doc


您仍然需要在视图上调用 render,并且由于集合的 fetch 是异步的,您不会有开箱即用的项目,因此您应该连接一个监听器。

首先,不要在集合的 initialize 中获取,这会使集合对任何其他用例几乎毫无用处。

var Posts = Backbone.Collection.extend({
  model: Post,
  url: 'http://localhost:4321/blogposts',
});

监听集合 sync 事件,然后在视图中获取。

var PostView = Marionette.ItemView.extend({
  el: '#content',
  template: Handlebars.compile($('#feed-post').html()),
  initialize: function () {
    this.listenTo(this.collection, 'sync', this.render);
    this.collection.fetch();
  },
});

Marionette甚至提供collectionEvents:

var PostView = Marionette.ItemView.extend({
  // ...snip...
  collectionEvents: {
    "sync": "render"
  }
  // ...snip...
});