Javascript MVVM:viewModel的架构应该像视图一样还是像模型一样

Javascript MVVM:viewModel的架构应该像视图一样还是像模型一样,javascript,mvvm,knockout.js,architecture,Javascript,Mvvm,Knockout.js,Architecture,在我们的KnockoutJS项目(一个MVVM数据绑定库)中,我们有两种类型的viewModel冲突。 一方面,我们拥有与视图类似的体系结构的视图模型。假设我有一个表单,允许我创建一个用户,它是一个formVM。viewModel的每个属性都是表单的属性。每个属性都是将写入业务模型的计算属性 另一方面,我们有一些视图模型,它们的架构与业务模型类似。在我们前面的示例中,它将是一个userVM,具有模型的基本属性以及其他属性,例如根据用户名计算的标签等。在视图html中,我们在这里使用userVM.

在我们的KnockoutJS项目(一个MVVM数据绑定库)中,我们有两种类型的viewModel冲突。 一方面,我们拥有与视图类似的体系结构的视图模型。假设我有一个表单,允许我创建一个用户,它是一个formVM。viewModel的每个属性都是表单的属性。每个属性都是将写入业务模型的计算属性

另一方面,我们有一些视图模型,它们的架构与业务模型类似。在我们前面的示例中,它将是一个userVM,具有模型的基本属性以及其他属性,例如根据用户名计算的标签等。在视图html中,我们在这里使用userVM.label作为示例


一个比另一个更正确吗?你用哪一种?

我认为两者都不正确。您的viewmodels中肯定不应该有任何业务逻辑。此逻辑属于您的业务层。viewmodel应该只保存一个模型(将可观察对象绑定到表单字段),并在适当的时候将其传递给业务层

严格地说,我认为viewmodel应该只包含视图(可观察对象)、事件处理程序的模型,而其他很少。当用户与UI交互时,事件处理程序将收集必要的信息并将其传递给业务层。此业务层可能会返回视图的数据,例如您提到的计算标签。然后可以将该值插入到“哑”可观察对象中,从而在视图中显示,而无需任何业务逻辑进入viewmodel

当用户点击save时,您从observables中获取数据并将其传递给业务层,业务层将做出响应(成功保存更改,或者出现问题)。viewmodel可以使用此响应来更新UI

简而言之,viewmodel处理UI显示的内容,并处理用户完成的任何交互。但它通常只包含将信息传递给包含智能的模块的哑功能


这是我的观点,老实说:实际上我自己也经常违反这一原则。

好吧,实际上你的回答是第一种方法是最好的。viewmodel使用computed自动更新业务模型这一事实是一个实现细节,因为我不想进入save按钮之类的问题。我自己也很喜欢这一理念,但我的前同事曾经断言,基于该模型的虚拟机可以具有在不同视图之间重用的属性。例如,如果我们在标题和用户面板中显示labelUsername,则不必指定两次计算的labelUsername,也不必在业务partWell中放置显示逻辑,这是我应该提到的:我将限制对视图/视图模型使用敲除。如果您使用Knockout(在本例中是computed标签)实现业务层,那么您的业务逻辑开始依赖于一个不适用于此的库。几乎不可能用Knockout替换Angular,因为Knockout将嵌套在应用程序的每一层中。标签的确定方式我称之为业务逻辑(有争议)。所以我要让它成为一个功能,而不是一个可观察的。哦,当然你会失去一些方便的功能,正如你提到的,当标签改变时,多个UI可能需要更新。通常,绑定到一个可观察对象会为您做到这一点。要做到这一点而不被淘汰,最简单的方法是发布/订阅机制。您的viewmodels可以订阅与它们相关的业务层事件,并在触发这些事件时更新它们的可观测值(例如,
pubsub.subscribe('label-changed',function(newLabelValue){myLabelObservable(newLabelValue);})
(简而言之:
pubsub.subscribe('label-changed',myLabelObservable);