2011-07-28 104 views
17

我在我的Backbone應用程序中有一個電子郵件視圖。它目前在我的控制器的view操作中實例化。它去有點像這樣:更改視圖的模型時,更換模型還是創建新視圖會更好?

routes: { 
    'email/:id': email 
}, 

//... 

email: function (id) { 
    var email = new Email({ 
    id: id 
    }); 
    this.emailView = new EmailView({ 
    model: email 
    }); 
    email.fetch(); 
} 

現在的問題是,如果我訪問一個郵件,然後另一個,我結束了創建兩個單獨的EmailView秒。這意味着,例如,EmailView中的刪除鏈接綁定到兩個單獨的Email模型,因此單擊刪除將刪除這兩個(不是一件好事)。

我正在尋找兩種解決方案。在一個,我會緩存EmailView,並更新其模型。然後問題是我不得不重新綁定中的events

另一種解決方案是創建一個新的EmailView,就像我現在一樣,但在替換之前解除舊的EmailView.el的事件。

我對此有何看法?有沒有更好的方法來處理這種情況?提前歡呼。

回答

3

爲每個模型實例創建一個單獨的視圖實例。每次您訪問新電子郵件時,請丟棄舊視圖並使用新電子郵件實例創建新視圖。

如果我猜的是左側的列表視圖和右側的編輯器,可能會出現什麼情況。您從左側的列表中選擇電子郵件,並且希望電子郵件正文出現在右側。

你真的想要5個視圖類。

PageView 
    has_one EmailCollectionView on left 
    has_one EmailEditorView on right 

EmailCollectionView 
    has_many EmailSummaryViews as vertical list 

EmailEditorView 
    has_one EmailView centered 

當您在EmailCollectionView單擊觸發事件是 拾起EmailEditorView它扔掉它EmailView 的舊實例,並呈現EmailView的新版本

類似的東西反正

+0

唯一的問題是,它不只是扔掉舊的EmailView的簡單情況。 DOM監聽器沒有被綁定,所以它們阻止舊視圖被垃圾收集。然後,當有人點擊「刪除」時,所有舊的電子郵件視圖都會收到。我認爲答案是在替換電子郵件視圖之前手動取消綁定這些偵聽器。 – Skilldrick

+0

你讓我擔心我現在的代碼; – bradgonesurfing

+1

看看jquery :: remove的文檔。 http://api.jquery.com/remove/哪個Backbone.js調用。事件處理程序會爲視圖的所有子元素自動收集垃圾。您仍然需要從模型綁定中分離,並綁定到其他視圖。但綁定到其他視圖是不好的。查看到查看事件應通過模型觸發。 – bradgonesurfing

2

我們最初創建新的視圖對象,每次有人會導航到例如「候選人/節目」,就像電子郵件的例子。該觀點將處理程序綁定到其持久性模型的「重置」事件。當我們從命令行重新設置該模型時,我們會看到儘可能多的事件觸發了該視圖的實例。換句話說,即使添加到DOM的元素都被完全銷燬,該視圖也不會被垃圾回收。

我們的解決方案是確保實例化我們的頂級視圖一次,然後讓他們在其初始化方法中創建子視圖。然後根據需要重新渲染它們。那麼你不必擔心垃圾收集的複雜性(據我所知,從我們的實驗中可以看出,這並不會發生)。

+0

好吧,愚蠢的問題:你怎麼能看到有多少事件被解僱?我從來沒有能夠找出這一個...... –

2

我認爲DOM事件處理程序應當由該視圖的remove()的調用方法來去除 - 見http://api.jquery.com/remove(下蓋,其骨幹調用)

如果覆蓋remove()方法也刪除像約翰尼建議的那樣綁定到任何模型事件,垃圾收集應該注意刪除視圖。

我落得這樣做重寫remove()方法來處理這個問題:

class EmailView extends Backbone.View 
    initialize:() -> 
     @model.bind('change', @render) 
    render:() => 
     # do some stuff 
    remove:() -> 
     @model.unbind('change', @render) 
     super() 

可以作爲這樣的路由器,然後使用:

routes: 
     'email/:id': email 

    //... 

    email: (id) -> 
     var email = new Email({ 
     id: id 
     }); 
     this.emailView.remove() if this.emailView 
     this.emailView = new EmailView({ 
     model: email 
     }); 
     email.fetch(); 
    } 

這將工作假設是,在所有事件視圖被綁定到正確的元素 - 也就是說,您在視圖中使用了@el(或this.el),並且每個視圖都有它自己的@ el/this.el。