2013-10-11 154 views
2

我想知道是否有可能以某種方式擴展Marionette Layout的機制是基於創建類似導航的堆棧。在木偶佈局中維護一堆木偶ItemViews

木偶行爲。

在區域show()的視圖之前,它在當前顯示的視圖上調用close()close()充當view的析構函數,解除所有事件的綁定,使其無用,並允許垃圾收集器處理它。

我的場景。

假設我有一個排序的導航機構,其中一個Layout充當控制器並首先顯示ItemView稱爲A,然後點擊某處允許切換到ItemView B.此時,動作上B(例如像點擊後退按鈕)允許返回到A 而不重新創建它

怎麼可能實現前面的場景而不再創建A 保持其狀態?

對於iOS用戶,我想模仿一種UINavigationController

有什麼建議嗎?

編輯

我的目標是恢復其狀態的分組緩存的視圖,而無需再次創建它。

我的場景如下。我有兩個區域的佈局:A B. 我在A內點擊某處並且A和B關閉以顯示C和D.現在,通過後退單擊可以恢復A和B的狀態。事件,模型等等,但是由於視圖是關閉的,事件被刪除。

回答

4

使用骨幹路由器來監聽URL更改事件。爲每個視圖設置路由,然後讓路由器調用佈局以更改它顯示的視圖以響應每個路由。用戶可以多次點擊或前進,應用程序會相應地進行響應並顯示正確的視圖。您的路由器可能是這樣的:

var Router = Backbone.router.extend({ 
    routes: { 
     'my/route/itemViewA': 'showItemViewA', 
     'my/route/itemViewB': 'showItemViewB' 
    }, 

    showItemViewA: function() { 
     layout.showItemView('a'); 
    }, 

    showItemViewB: function() { 
     layout.showItemView('b'); 
    } 
}); 

您的佈局可能會是這個樣子:

var Layout = Backbone.Marionette.Layout.extend({ 

    regions: { 
     someRegion: 'my-region-jquery-selector' 
    }, 

    initialize: function() { 
     this.createViews(); 
    }, 

    createViews: function() { 
     this.views = { 
      a: new Backbone.Marionette.ItemView, 
      b: new Backbone.Marionette.ItemView 
     }; 
    }, 

    showItemView: function (view) { 
     this.someRegion.show(this.views[view]); 

     // You might want to do some other stuff here 
     // such as call delegateEvents to keep listening 
     // to models or collections etc. The current view 
     // will be closed but it won't be garbage collected 
     // as it's attached to this layout. 
    } 
}); 

路由器和佈局之間的通信的方法,並不一定是直接調用。您可以觸發進一步的應用程序範圍內的事件或做任何您能想到的事情。上面的路由器非常基本,但可以完成工作。您可以創建一個更智能的路由器來使用帶參數的單個路由來動態確定要顯示哪個itemView。

每當用戶做某些事情需要更改視圖時,您可以使用router.navigate('my/route/itemViewB', {trigger: true});來更新瀏覽器的歷史記錄。此外,如果您將應用設置爲只在歷史更改事件上呈現,則不需要設置兩種機制來銷燬每個視圖。

我在我自己的應用程序中使用這種模式,它工作得很好。

+0

感謝您的回覆。在這種情況下,如果可能的話,我會避免路由機制。有什麼建議? –

+0

你已經說過,點擊後退按鈕需要點擊事件,並且依靠收聽URL更改事件。任何其他解決方案都只是複製路由器的功能。有沒有特別的原因你不想使用它?注:剛剛意識到我可能已經留下了一點關鍵信息,所以我已經更新了我的答案。 – Simon

+0

感謝您的支持。你能告訴你如何實現'showItemViewA'?我的目標是以下。不要再創建視圖,但要恢復先前保存的視圖。 –

3

@西蒙的回答是朝着正確的方向。但是,阻止Marionette關閉視圖的唯一方法是修改它的一部分區域代碼。

var NoCloseRegion = Marionette.Region.extend({ 
    open: function(view) { 
     // Preserve the currentView's events/elements 
     if (this.currentView) { this.currentView.$el.detach(); } 

     // Append the new view's el 
     this.$el.append(view.el); 
    } 
}); 

的時候務必創建佈局視圖時

var Layout = Backbone.Marionette.Layout.extend({ 
    regions: { 
     someRegion: { 
      selector: 'my-region-jquery-selector', 
      regionType: NoCloseRegion 
     }, 
    }, 
    initialize: function() { 
     this.createViews(); 
    }, 
    createViews: function() { 
     this.views = { 
      a: new Backbone.Marionette.ItemView, 
      b: new Backbone.Marionette.ItemView 
     }; 
    }, 
    showItemView: function (name) { 
     // Don't `show`, because that'll call `close` on the view 
     var view = this.views[name]; 
     this.someRegion.open(view) 
     this.someRegion.attachView(view) 
    } 
}); 

現在,而不是調用show其關閉舊觀點來指定我們新的地區級,呈現新的,並將其附加到該地區(並觸發一些事件),我們可以分離舊視圖,附加新視圖並打開它。