Marionette CompositeView 为 Collection 中的每个模型呈现自身,而不是 ItemView (Marionette Rails)

Posted

技术标签:

【中文标题】Marionette CompositeView 为 Collection 中的每个模型呈现自身,而不是 ItemView (Marionette Rails)【英文标题】:Marionette CompositeView renders itself for each Model in Collection instead of ItemView (Marionette Rails) 【发布时间】:2013-10-08 06:38:51 【问题描述】:

基本上,我试图将 CompositeView 呈现为带有表头的简单四列列表,其中集合中的每个模型都呈现为 a 并附加到 .我非常密切地关注an example of Derick's,只有一点点变化,但不幸的是得到了一些非常奇怪的结果。

视图不是渲染每个 itemView,而是引用自身并为集合中的每个项目重新渲染,生成一个新的表和表头。在此之前,它是在自己渲染compositeView。

我有一个 itemView,它的模板是一组项目,以及一个引用它的复合视图,它是一个表

复合视图:

class App.module('Views.Parts').Index extends Backbone.Marionette.CompositeView
   template: 'parts/index'
   itemView: App.Views.Parts.Part
   tagName: 'table'
   itemViewContainer: 'tbody'
   appendhtml: (collectionView, itemView, index)->
           collectionView.$el.append(itemView.el)

ItemView:

class App.module('Views.Parts').Part extends Backbone.App.ItemView
       tagName: 'tr'
       template: 'parts/part'
       events:
               "click .destroy": "destroy"
       destroy: (e) ->
               e.preventDefault()
               @model.destroy()
       onRender: ->
               @stickIt()

控制器

class App.Controllers.Parts
       constructor: ->
               @parts = new App.Collections.Parts
               @parts.reset(App.parts)
               App.parts = null

       showView: (view)->
               App.mainRegion.show view

       index: ->
               view = new App.Views.Parts.Index
                       collection: @parts
               @showView view

我还听说有必要在 CompositeView 之前声明一个 ItemView ——但是由于它是一个 Marionette Rails 项目,因此视图实际上位于不同的目录中。我是否必须声明它们的顺序或以其他方式将它们相互绑定?

【问题讨论】:

【参考方案1】:

TL;DR Marionette.CompositeView 如果未定义,则将其自身用作项目视图类型。在原型上设置 itemView 属性以使其使用正确的项目视图

问题

在我们的案例中,问题是 Marionette 通过 following logic 获取 CompositeViewItemView

getItemView: function(item)
  var itemView = Marionette.getOption(this, "itemView") || this.constructor;

  if (!itemView)
    throwError("An `itemView` must be specified", "NoItemViewError");
  

  return itemView;

我们将 CompositeView 定义为:

class sm.Views.GreetingPicker extends Marionette.CompositeView
  template: 'greeting_picker'
  el: '.message-choice'
  itemView: sm.Views.WelcomeMessage

CompositeViewItemViewLayout 将它们捆绑在一起时(由 Rails 使用 Sprockets 提供服务),文件加载一下子就没有问题了。

在我拆分 LayoutCompositeViewItemView 之后,CompositeView 的 appendHtml 的两个参数都是与 CompositeView 的类型相同。这是因为开头提到的木偶逻辑造成的。

解决方案

在初始化程序中手动设置构造函数的 itemView 属性。像这样:

class sm.Views.GreetingPicker extends Marionette.CompositeView
  initialize: ->
    @constructor::['itemView'] = sm.Views.WelcomeMessage

【讨论】:

谢谢!我刚刚解决了一个类似的问题,自然而然地在我发布我的问题后就遇到了这个解决方案。【参考方案2】:

您不想拥有itemViewContainerappendHtml。尝试删除后者,您的视图应该会正确呈现。

【讨论】:

谢谢。我们最终通过修复了渲染问题的 require 树更改了声明顺序(表格有效!)。我们仍然拥有itemViewContainerappendHtml。这可能会在以后导致什么样的问题? 对于初学者来说,您的 appendHtml 代码对应于默认行为,因此不需要它。这可能会导致问题,因为它们都在告诉集合视图在哪里添加新的项目视图,这可能会导致冲突。 只是写信确认取出 appendHtml 代码仍然按预期呈现一切。感谢您的提示!

以上是关于Marionette CompositeView 为 Collection 中的每个模型呈现自身,而不是 ItemView (Marionette Rails)的主要内容,如果未能解决你的问题,请参考以下文章

使用backbone.marionette获取“NoTemplateError:找不到模板”

使用 Jasmine 单独测试 Marionette 模块

CoffeeScript/Backbone/Marionette - 教程示例转换和范围问题

如何使用 Marionette 创建全局按键事件侦听器

如何在 marionette.js 框架 CollectionView 中调用 Web 服务

Backbone.Marionette vs Backbone-Boilerplate