2012-03-10 46 views
2

我被困在以下問題上:Backbone.js:如何處理單個視圖的選擇?

我有一個屬性模型,它定義了它是否可視化選擇或不是,我將爲此問題調用SelectModel。

SelectModel = Backbone.Model.extend({ 
defaults:{ 
isSelected: false 
} 
}) 

現在我沒有得到的第一部分是我應該如何處理一般選擇。 如果我想使用觀察者模式,我的視圖應該聽取isSelected屬性的更改。但我的觀點首先觸發了這一點,所以我會這樣做。

SelectView = Backbone.View.extend({ 
initialize: function(){ 
this.model.bind("change:isSelected", this.toggleSelectionVisually) 
}, 

events: { 
"click" : toggleSelection 
}, 

toggleSelection: function(){ 
this.model.set({"isSelected": !this.model.get("isSelected"); 
}, 

toggleSelectionVisually:(){ 
//some code that shows that the view is now selected 
}, 
}) 

所以這本身已經感覺有點荒唐,但我想我才明白了什麼。

但是我真正無法實現的部分卻沒有讓我的代碼變得可怕,就是處理多個模型的選擇,一次只選擇一個模型。

SelectListView = Backbone.View.extend({ 
initialize: function(){ 
this.collection = new SelectList(); 
}, 

toggleSelection: function(){ 
???? 
} 
}) 

那麼誰應該通知選擇對象誰改變了?哪個部分應該觸發它,哪個部分應該聽?我真的被困在這一個。對於單個View來說,這是可行的,對於一個集合我很遺憾地丟失了。

回答

3

我會建議以下簡化爲您SelectView直到我看到你問題的第二部分:

SelectView = Backbone.View.extend({ 
    events: { 
    "click" : toggleSelection 
    }, 

    toggleSelection: function(){ 
    this.model.set({"isSelected": !this.model.get("isSelected"); 
    //some code that shows whether the view is selected or not 
    } 
}); 

但是,由於isSelected屬性顯然是相互排斥的,因此當另一個打開時可以隱式切換,我認爲您擁有它的方式最適合您的情況。

所以,使用你現有的SelectView,你可以有一個SelectListView如下。 警告:每次選擇一個模型時,它會遍歷整個模型集合。如果你將有大量的模型,這將不能很好地擴展,你需要緩存先前選擇的模型,而不是迭代整個集合。

SelectListView = Backbone.View.extend({ 
    initialize: function(){ 
    this.collection = new SelectList(); 
    this.collection.bind('change:isSelected', this.toggleSelection, this); 
    }, 

    toggleSelection: function(toggledModel){ 
    //A model was toggled (on or off) 
    if(toggledModel.get('isSelected') { 
     //A model was toggled ON, so check if a different model is already selected 
     var otherSelectedModel = this.collection.find(function(model) { 
     return toggledModel !== model && model.get('isSelected'); 
     }); 

     if(otherSelectedModel != null) { 
     //Another model was selected, so toggle it to off 
     otherSelectedModel.set({'isSelected': false}); 
     } 
    } 
    } 
}); 
+0

謝謝,我喜歡與前面選擇的緩存這一個最好的一起。 – Daniel 2012-03-10 17:00:08

0

有不同的方法可以做到這一點。您可以在集合本身上觸發事件,並讓所有SelectModel實例監聽它並相應地進行更新。如果集合中有很多SelectModel實例,那麼這看起來有點浪費,因爲它們中的大多數實例最終都不會做任何工作。我可能會做的是保持跟蹤的最後SelectModel在你的視野:

SelectListView = Backbone.View.extend({ 
    initialize: function(){ 
    this.collection = new SelectList(); 
    this.lastSelectedModel = null; 
    }, 

    toggleSelection: function(){ 
    // populate newSelectedModel with the SelectedModel that you're toggling 
    var newSelectedModel = getNewSelectedModel(); 

    if (!newSelectedModel.get('isSelected')) { 
     // if the SelectModel isn't already selected, we're about to toggle it On 
     // so we need to notify the previously selected SelectModel 
     if (this.lastSelectedModel) { 
     this.lastSelectedModel.set({isSelected: false}); 
     } 
     this.lastSelectedModel = newSelectedModel; 
    } else { 
     // if the newSelectedModel we're about to toggle WAS already selected that means 
     // nothing is selected now so clear out the lastSelectedModel 
     this.lastSelectedModel = null; 
    } 
    newSelectedModel.set({isSelected: !newSelectedModel.get('isSelected')}); 
    } 
}) 
3

我會建議你的模型不會跟蹤這個,而是視圖。

在我看來,模型與其顯示無關,而是您正在跟蹤的數據。該視圖應封裝有關數據在何處以及如何顯示給用戶的所有信息

因此,我會將isSelected作爲視圖上的屬性。然後編寫一個切換可見性的方法是很簡單的。然後,如果您需要解釋另一個觀點,即在特定的視圖中選擇就可以把聽衆$(this.el).on('other_visible', toggle_show),你可以在你的toggle_visibility方法觸發與​​

+0

我認爲你是對的。雖然可悲的是,我必須重新使用你的建議的數量在這一點上是相當大的。 – Daniel 2012-03-10 17:09:34

+0

啊重構難題。我不得不重寫我們網站的60%,以改變我們的音頻播放器如何繼承我們的觀點。它吹得很厲害;我和你在一起。 – tkone 2012-03-10 19:37:10

2

非常接近由@rrr建議的解決方案,但來自移動邏輯ViewCollection,我認爲這波紋管:

SelectsCollection = Backbone.Collection.extend({ 
    initialize: function() { 
    this.on("change:selected", this.changeSelected); 
    }, 

    changeSelected: function(model, val, opts){ 
    if(val){ 
     this.each(function(e){ 
     if(e != model && e.get("selected")) e.set("selected", false); 
     }); 
    }; 
    }, 
}); 
相關問題