2013-10-08 67 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

編輯我的答案 –