2013-10-08 38 views
4
的ItemView控件

我会用一个清晰​​的问题开始,之后解释在递归结构:
如何正确封装的模型,包含在CompositeView,为ItemView渲染使用CompositeView中,而封装每个模型与木偶

我的问题很简单,但我无法设法得到一些好的工作。 我有一棵笔记。 每个音符是Backbone.model并具有@descendants集合,然后 我有一个Backbone.Collection代表该树(其中@descendants是一个实例) 我设置基本CollectionView,以作为itemView,该CompositeView 。一切都完美呈现,我对此感到非常高兴。这个工作解决方案显示在第一个代码片段中!

问题来了。在此基础上,我有点碰到这个问题:Events fired for whole hierarchy 这对我的事件如何绑定是有意义的。起初,我只是添加了独特的选择器(添加了data-guid到我的html元素,所以我可以通过它得到它们),它运作正常,虽然它已经变得“哈克”。但其他类似的问题已经上升,所以我决定我需要一个解决方案。 因此,我告诉myslef,让我们将每个模型封装在一个ItemView中,并使用Composite视图递归地呈现它们。 但是......这并不是在所有的世界最好...

以下是我在开始时:

class Note.ModelView extends Marionette.CompositeView 
    template: "note/noteModel" 
    id: "note-item" 
    itemViewContainer: ".note-descendants" 
    ui: 
    noteContent: ".noteContent" 
    events: 
    "keypress .noteContent": "createNote" 
    "click .destroy": "deleteNote" 
    # ... 
    initialize: -> 
    @collection = @model.descendants 
    # ... 

class Note.CollectionView extends Marionette.CollectionView 
    id: "note-list" 
    itemView: Note.ModelView 
    initialize: -> 
    @listenTo @collection, "sort", @render 

现在我调到属于渲染模型的每一件事新ItemView控件

class Note.ModelView extends Marionette.ItemView 
    template: "note/noteModel" 

    ui: 
     noteContent: ".noteContent" 
    events: -> 
     guid = @model.get 'guid' 
     events = {} 
     events["keypress #noteContent#{guid}"] = "createNote" 
     events["blur #noteContent#{guid}"] = "updateNote" 
     events["click #destroy#{guid}"] = @triggerEvent 'deleteNote' 

    initialize: -> 
     @bindKeyboardShortcuts() 
     @listenTo @model, "change:created_at", @setCursor 

    class Note.TreeView extends Marionette.CompositeView 
    template: "note/parentNote" 
    itemView: Note.ModelView 

    initialize: -> 
     @collection = @model.descendants 
     @listenTo @collection, "sort", @render 
     _.bindAll @, "renderItem" 
    renderItem: (model) -> 
     if model.get('parent_id') is 'root' 
     itemView = new Note.ModelView model: model 
     itemView.render() 
     @$el.append itemView.el 
    onRender: -> 
     @collection.each this.renderItem 
     @renderItem @model 
    appendHtml: (collectionView, itemView) -> 
     @model.descendants.each (note) => 
     iv = new Note.ModelView model: note 
     iv.render() 
     @.$('.note-descendants').append iv.el 


    class Note.CollectionView extends Marionette.CollectionView 
    id: "note-list" 
    itemView: Note.TreeView 
    initialize: -> 
     @listenTo @collection, "sort", @render 

和noteMode模板(parentNote只是一个空的模板现在)

<button class="btn btn-danger btn-xs untab">UN</button> 
<button class="btn btn-success btn-xs tab">TAB</button> 
<div class="noteContent">{{{indent}}}{{{title}}}</div> 
<button class="destroy"></button> 
<div class="note-descendants"></div> # That is where I'm putting the children notes 

所以这几乎工作。但它很黑,而且它仍然不起作用。我一直在阅读所有文档,并且我已经阅读了Derick Bailey on nested structure and CompositeViewDavid Sulc on Nested Views这两个链接,但我仍然觉得我错过了一些重要的细节。

我在寻找什么,作为答案,是任何暗示或任何常用的方式来管理这与木偶。我真的在寻找一些干净的东西,因为这将成为应用程序构建的角色之一。
也许我在错误的地方搜索?任何事情都会受到欢迎!非常感谢你

祝你一切安好。 谢谢你的时间。

+0

工作演示 - http://jsfiddle.net/derickbailey/AdWjU,细节 - http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and -more/ –

+0

谢谢你链接已经在问题中的链接! – Mikechaos

+0

对不起。 –

回答

3

我将用你的不同词语向你解释Derick Bailey在你引用的博客文章中已经陈述了什么。

查看

需要两个意见,使这项工作。

第一个“母视图”是包含递归结构作为其子节点的最外层视图。这可以是Marionette.CollectionView或Marionette.CompositeView。

第二个视图是您的递归视图,这意味着它需要是Marionette.CompositeView。通过不指定“itemView”属性来制作Marionette.CompositeView递归。在缺少itemView属性的情况下,Marionette.CompositeView将使用ITSELF来呈现它给出的集合的模型。

收集

你需要一个集合,或者是一个嵌套Backbone.Collections的Backbone.Collection,或只是其中包含嵌套很深的哈希Backbone.Collection。在后一种情况下,当将它们交给Marionette.CompositeView(如下面的RecursiveView的initialize()方法)时,您不需要忘记将简单哈希值转换为Backbone.Collections。

全部放在一起

var RecursiveView = Marionette.CompositeView.extend({ 
    template: '#someTemplate', 
    initialize: function() { 
     this.collection = this.model.get('children') 
    } 
}); 

var MotherView = Marionette.CollectionView.extend({ 
    itemView: RecursiveView, 
    collection: new Backbone.Collection([{key: 'value', children: [{}, {}, {}]}]) 
}); 

问题:事件冒泡

当然,DOM事件现在冒泡,所以这段代码

var RecursiveView = Marionette.CompositeView.extend({ 
    events: { 
     'click button': someCallback 
    } 
}); 

将是一个catch - 所有参考的视图事件以及它的所有后代。

该问题的最简单解决方案是使用直接后代css selectr >,例如,

var RecursiveView = Marionette.CompositeView.extend({ 
    events: { 
     'click >button': someCallback 
    } 
}); 

如果这还不够,一个有效的解决方案是防止自动事件冒泡,例如,

var RecursiveView = Marionette.CompositeView.extend({ 
    events: { 
     'click button': function (event) { 
      event.stopPropagation(); 
      // or event.stopImmediatePropagation() depending on your use case 
      // cf. http://stackoverflow.com/a/5299841/899586 and 
     } 
    } 
}); 
+0

此代码与我发布的第一个代码有什么区别?没有...我有这个工作非常感谢你。我正在寻找一种方法来封装生成的html,因此最内层的视图只能访问其html,而不能访问整个层次结构html。 – Mikechaos

+0

好吧,对不起,误解您的帖子,诚实的错误。 为什么不添加直接后代选择器'>'以便仅检查发生在直接后代的DOM事件? 如果这还不够,我宁愿在事件传播方面攻击问题:在递归视图中停止事件冒泡。 –

+0

编辑我的答案 –