2014-10-01 17 views
1

在我們的KnockoutJS項目(一個MVVM數據綁定庫)中,我們有兩種類型的viewModel發生了碰撞。 一方面,我們有視圖建模像視圖的模型。假設我有一個允許我創建用戶的表單,它是一個formVM。並且viewModel的每個屬性都是該窗體的屬性。每個屬性都是一個計算結果,將寫入業務模型。MVVM:viewModel應該像視圖一樣架構還是像模型一樣

另一方面,我們有視圖模型,像商業模式一樣架構化。在我們前面的例子中,它將是一個用戶VM,具有模型的基本屬性加上其他諸如從用戶名等計算出的標籤。並且在視圖html中,我們在這裏使用userVM.label作爲例子。

比另一個更正確嗎?你使用哪一個?

回答

2

我會說這兩個都是不正確的。在你的視圖模型中肯定不應該有任何業務邏輯。這個邏輯屬於你的業務層。視圖模型應該只包含一個模型(將觀察值綁定到您的表單域),並在適當的時候將其傳遞給業務層。

嚴格來說,我會說viewmodel應該只包含您的視圖(observables),事件處理程序和其他很少的模型。當用戶與UI進行交互時,您的事件處理程序將收集必要的信息並將其傳遞給業務層。此業務層可能會返回視圖的數據,例如您提到的計算標籤。這個值然後可以被插入到一個'啞'觀察,因此可以顯示在視圖中,沒有任何業務邏輯進入你的視圖模型。

當用戶點擊保存時,您從observables中獲取數據並將其傳遞給業務層,該層將響應(更改成功保存或出錯)。視圖模型可以使用此響應來更新UI。

簡而言之,viewmodel處理UI顯示的內容,並處理用戶完成的任何交互。但它通常只包含愚蠢的功能,將信息傳遞給包含智能的模塊。

這就是我的看法,說實話:在實踐中我自己經常違反這個原則。

+0

嗯,實際上你回答說第一次接近是最好的。事實上,視圖模型自動更新計算的業務模型是一個實現細節,因爲我不想進入保存按鈕等問題。我自己也非常喜歡這種哲學,但我的前同事用它來表明基於模型的虛擬機可以具有在不同視圖中重複使用的屬性。例如,如果我們在標題和用戶面板中顯示我們的labelUsername,則不必指定兩次計算的labelUsername,也不必在業務部分中放置顯示邏輯 – 2014-10-01 09:17:50

+0

嗯,這是我應該提到的:我會將Knockout的使用限制在您的視圖/視圖模型中。如果您使用Knockout實現業務層(在本例中爲計算標籤),則您的業務邏輯開始依賴於不適合此類的庫。因爲Knockout將嵌套到應用程序的每一層,所以對於Angular來說,將永遠不會交換Knockout。標籤的確定方式是我稱之爲業務邏輯(有爭議的)。所以我會做一個函數,而不是可觀察的。 – 2014-10-01 09:52:58

+0

噢,當然你會失去一些方便的功能,正如你所提到的,當標籤更改時,可能需要更新多個用戶界面。通常綁定一個可觀察對象會爲你做到這一點。沒有Knockout的最簡單的方法是發佈/訂閱機制。您的視圖模型可以訂閱與它們有關的業務層事件,並在觸發這些事件時更新它們的可觀察事件(例如'pubsub.subscribe('label-changed',function(newLabelValue){myLabelObservable(newLabelValue);});'(或簡而言之:'pubsub。subscribe('label-changed',myLabelObservable);') – 2014-10-01 09:55:02