MVC和MVVM有什么区别?

1439

标准的“模型视图控制器”(MVC)模式和微软的Model/View/ViewModel(MVVM)模式有区别吗?


82
请注意,尽管MVVM是由微软创造的术语,但许多非微软的开发者和项目开始采用这种模式。这条评论由反对微软恶意攻击部门提供。 - BoltClock
3
在使用MVVM很长一段时间后,我第一次尝试MVC时感到沮丧,直到我学会了如何使用MVVM中的绑定技术将ViewModel传递给浏览器。但正如Joel所说,从浏览器获取状态的唯一方式是通过以名称/值对形式提交更改的表单。如果你不理解这一点,那么在MVC中会���到困难。把控制器看作视图的依赖注入器就可以了。 - JWP
6
这是一个在高级[设计模式]上被点赞的问题。我想友好地建议在回答中使用图表。 - Ricardo
1
也重新构思问题,以反映问题是在微软技术的背景下提出的......尽管接受的答案似乎不是如此。 - Raydot
5
这是Joel的文章的存档版本:https://web.archive.org/web/20150219153055/http://joel.inpointform.net/software-development/mvvm-vs-mvp-vs-mvc-the-differences-explained/。 - Tereza Tomcova
4
与MVC不同,ViewModel并不是一个控制器。它相反地作为一个绑定器,将数据绑定在视图和模型之间。而MVC格式专门设计用于在模型和视图之间创建关注点分离,带有数据绑定的MVVM格式则特别设计用于允许视图和模型直接通信。 - Ahmad Ismail
24个回答

746

MVC/MVVM不是一个要么……要么的选择。

这两种模式在ASP.Net和Silverlight/WPF开发中以不同的方式出现。

对于ASP.Net,MVVM用于视图内部的双向数据绑定。通常这是一个客户端实现(例如使用Knockout.js)。而MVC则是一种在服务器端分离关注点的方式。

对于Silverlight和WPF,MVVM模式更为全面,可以看作是替代MVC(或者其他将软件分成独立职责的模式)的方式。一个常见的误解是,ViewModel仅仅替换了MVC中的控制器(好像你只需要在首字母缩写中用VM替换C就行了)...

ViewModel并不一定可以替代需要单独控制器的情况。

问题在于:为独立测试*和特别是需要重用时,视图模型不知道显示它的视图是什么,更重要的是,也不知道它的数据来自哪里。

*注意:实际上,控制器从ViewModel中移除了大部分需要进行单元测试的逻辑。因此,VM变成了一个简单的容器,几乎不需要进行任何测试。这是一件好事,因为VM只是设计师和编码人员之间的桥梁,所以应该保持简单。

即使在MVVM中,控制器通常也包含所有处理逻辑,并决定在哪些视图中使用哪些视图模型显示哪些数据。

从我们目前看到的情况来看,ViewModel模式的主要好处是将代码从XAML代码后台中移除,从而使XAML编辑成为一个更独立的任务。我们仍然会根据需要创建控制器来控制应用程序的总体逻辑。

我们遵循的基本MVCVM指南如下:

  • 视图显示一定形状的数据。它们不知道数据来自哪里。
  • ViewModels 保存特定形式的数据和命令, 它们不知道数据或代码来自哪里,也不知道如何显示。
  • Models 保存实际数据(各种上下文、存储或其他方法)。
  • Controllers 监听并发布事件。控制器提供控制所见数据及其位置的逻辑。控制器向 ViewModel 提供命令代码,使 ViewModel 可以被重用。

我们还注意到,Sculpture 代码生成框架 实现了 MVVM 模式和类似于 Prism 的模式,并且它还广泛使用控制器来分离所有用例逻辑。

不要假设控制器被 View-models 取代了。

我已经开始写关于这个主题的博客,在以后我会继续添加文章(仅存档因为托管丢失)。将 MVCVM 与常见导航系统结合存在问题,因为大多数导航系统只使用 Views 和 VMs,但我将在以后的文章中详细探讨这个问题。

使用 MVCVM 模式的另一个好处是,只有控制器对象需要在应用程序的生命周期内存在,并且控制器主要包含代码和很少的状态数据(即很小的内存开销)。这使得应用程序比需要保留视图模型的解决方案具有更少的内存消耗,并且它非常适合某些类型的移动开发(例如使用 Silverlight/Prism/MEF 的 Windows Mobile)。当然,这取决于应用程序的类型,因为您可能仍然需要保留偶尔缓存的 VM 以提高响应速度。

注意:这篇文章被多次编辑过,并且没有针对狭窄的问题进行具体说明,因此我已经更新了第一部分来涵盖它。下面的评论中许多讨论只涉及ASP.Net而不是更广泛的情况。本文旨在探讨在Silverlight、WPF和ASP.Net中更广泛地使用MVVM,并试图劝阻人们用ViewModels替换控制器。


9
@Tomasz Zielinski:确实,但“它们被用在哪里”不是问题(或者说不是我回答的重点)。我的观点是,在MVVM中控制器仍然很有用。 - iCollect.it Ltd
61
我同意。我的评论是突然有所领悟而产生的,而不是因为我不同意你的观点。 - Tomasz Zieliński
1
我们还使用控制器来控制向导式UI中视图的“流程”。 - riezebosch
4
@Justin: 我发现我的那个句子用词有点模糊。实际上我是指所有组件的单元测试都更容易被支持,而不仅仅是针对ViewModel的测试(正如你所指出的,在MVCVM中ViewModel并没有做太多事情...这也是你想要的)。控制器的真正好处在于你实际上将大部分测试要求从ViewModel中移除了(人们一直在将控制器逻辑塞到ViewModel中),并将其放到可以进行测试的地方(主要是控制器和模型)。“重用”这个评论是特定针对那个句子中的ViewModel。我已经修改了它。 - iCollect.it Ltd
11
@TomaszZielinski M(MVVM)C - Mohamed Emad
显示剩余24条评论

340

我认为理解这些缩写的最简单方法是先暂时抛开它们。相反,想一想它们所起源的软件,它们中的每一个。实际上,这只涉及早期Web和桌面之间的区别。

随着它们在2000年代中期变得越来越复杂,MVC软件设计模式 - 首次描述于1970年代 - 开始应用于Web应用程序。想想数据库、HTML页面和代码之间的关系。让我们稍微完善一下,以达到MVC:对于“数据库”,让我们假设数据库加上接口代码。对于“HTML页面”,让我们假设HTML模板加上模板处理代码。对于“代码之间”,让我们假设代码映射用户点击到行动,可能会影响数据库,肯定会导致显示另一个视图。至少在这个比较的目的上就是这样。

让我们保留这个Web方式的一个特征,不是像今天这样存在,而是10年前存在的样子,当时JavaScript是一种低劣、可鄙的烦恼,真正的程序员最好远离它:HTML页面基本上是愚蠢且被动的。浏览器是一个轻客户端,或者说,一个贫客户端。浏览器中没有智能。全页面刷新是主流。每次都要重新生成“视图”。

让我们记住,尽管这种Web方式很流行,但与桌面相比,它非常落后。桌面应用程序是肥客户端或富客户端。 (即使像Microsoft Word这样的程序也可以被认为是某种类型的客户端,一个文档客户端。)它们充满了智能,充满了关于数据的知识。它们是有状态的。它们将处理的数据缓存在内存中。完全没有全页面刷新这种鬼东西。

而这种富桌面方式可能就是第二个缩写MVVM的起源。不要被字母所迷惑,也不要因为省略了C而被愚弄。控制器仍然存在。他们必须存在。没有任何东西被删除。我们只是增加了一件事:状态,客户端上缓存的数据(以及处理该数据的智能)。那些数据,本质上是客户端上的高速缓存,现在被称为“ViewModel”。它是允许丰富互动性的东西。 就是这样。

  • MVC=模型(Model)、控制器(Controller)、视图(View),本质上是单向通信,互动性差。
  • MVVM=模型(Model)、控制器(Controller)、缓存(Cache)、视图(View),双向通信,互动性丰富。

我们可以看到,通过Flash、Silverlight和最重要的JavaScript,Web已经采用了MVVM。浏览器不再合理地被称为轻客户端。看看它们的可编程性,看看它们的内存消耗,看看现代网页上所有的Javascript互动性。

个人认为,通过观察具体事物来理解这些理论和缩写更容易理解。抽象的概念很有用,尤其是在具体事物上进行演示时,理解可能会变得更加全面。

 


60
MVC 不是起源于 Web。Trygve Reenskaug 在 1970 年代将 MVC 引入了 Smalltalk-76。 - Arialdo Martini
12
即使将其改为“MVC是通过Web应用程序设计而普及的”,我认为这是没有正确引用的猜测。 - Dan Bechard
5
Arialdo:谢谢,我不知道Smalltalk-76。那时我玩其他的玩具。开个玩笑,有趣的是一些概念是多么古老。-@Dan,我写的是:“[MVC]可能早在[网络]之前就存在了,但网络是它如何被推广到网页开发者大众中的方式。”我仍然认为这是正确的。我没有引用,但我觉得我不需要引用,因为当我在上一个十年初成为网页开发者时,MVC的推广是我个人经历的一部分。当时,Apache Struts非常流行,并且有很多用于MVC的bean。 - Lumi
7
MVC并不是“基本上单向通信”的模式,因为浏览器经常发出Get和Post请求。无论是Get还是Post都可以改变查询字符串中的字段值。这为浏览器提供了充足的机会将信息发送回控制器。MVC是建立在HTTP 1.0之上的,该协议始终考虑到双向通信。 - JWP
23
谢谢,Lumi。相比其他答案,这个回答让我更易理解。它是否正确我不知道,但从我的角度来看,至少是连贯的。 - gcdev
显示剩余7条评论

184

MVVM 模型-视图-视图模型 与MVC(模型-视图-控制器)类似。

控制器视图模型 替代。视图模型位于UI层下方。视图模型公开视图所需的数据和命令对象。您可以将其视为视图从中获取数据和操作的容器对象。视图模型从模型中提取其数据。

Russel East 写了一篇博客,详细讨论了MVVM与MVC不同之处


95
“将控制器替换为视图模型”这个句子是不正确的。在MVVM中,控制器的角色是数据绑定(或者如果你使用那种方式,则是约定绑定)。 - DaniCE
10
只有在使用WPF的双向数据绑定时,MVVM才有意义。否则,MVC/MVP等将足以满足需求。 - Jeff
307
如果你把十个软件架构师放在一起讨论模型-视图-控制器模式是什么,最终可能会得出12种不同的意见。 - sll
10
@OmShankar 第11个并不是你自己的意见。总共有10个人,12种不同的看法。这句谚语旨在暗示这些模式的定义是如此开放和主观的,以至于至少有两个人会感到困惑,从而产生多种不同的观点。 - Dan Bechard
10
这实际上是WPF数据绑定和微软发明的MVVM的重点所在,其可以完全绕过控制器。认为句子“The controller is being replaced with a View Model”不正确,仅因为幕后有一个控制器,就像声称“高级语言用更易读的语言替代了晦涩难懂的机器码”一样,因为机器语言仍在幕后使用,这种说法也是不正确的。 - yoel halb
显示剩余7条评论

103

首先,MVVM是MVC模式的一种进阶,它使用XAML来处理显示。 这篇文章概述了两种模式的某些方面。

Model/View/ViewModel架构的主要重点似乎在于,在数据(“Model”)之上,有另一层非可视组件(“ViewModel”),将数据的概念更紧密地映射到数据的视图的概念(“View”)。由View绑定到ViewModel,而不是直接绑定到Model。


25
我认为你引用的段落已经总结得很好了。ViewModel 的一个特点是它是模型针对视图进行扁平化/修改后的版本。许多其他的 MV* 模式都会绑定到 真正的 模型上。 - Daniel Auger
3
“许多其他MV*模式再次绑定实际模型”?真的吗?我原以为在MVC中视图总是要与控制器绑定,无论如何。 - Debajit
10
在传统的MVC架构中,视图与控制器联系不太紧密,它主要与模型绑定。可以将其想象成一个机器人 - 模型代表机器人关节的位置,视图是LCD显示器,您可以在上面看到机器人,控制器则可以是键盘。在这样的设置中,视图取决于模型,也就是说,您在监视器上看到的机器人的空间位置是模型的直接表示。 - Tomasz Zieliński
1
@Nocturne,丹尼尔似乎是在说,虽然官方上所有的MV*都应该使用单独的VM,但许多开发人员会忽略它,直接传递实际的模型。事实上,在MVC等规范中并没有禁止这样做,但在MVVM中,必须有一个VM负责模型和视图之间的转换。 - yoel halb
2
我会这样说:模型是最接近数据库模式的东西。当查询运行时,它可以在模型层将数据投影到强类型中。视图模型是包含许多东西的集合,包括模型对象,但也可以并且确实保持与数据相关的视图状态。控制器只是在视图模型和视图之间充当交通警察,而视图仅关注视图状态。 - JWP

61

Microsoft在此提供了Windows环境下MVVM设计模式的解释

以下是其中关键部分:

在Model-View-ViewModel设计模式中,应用程序由三个通用组件组成。 enter image description here

  • Model:表示应用程序消耗的数据模型。例如,在图片共享应用中,此层可能代表设备上可用的图片集和用于读取和写入图片库的API。

  • View:应用程序通常由多个UI页面组成。每个向用户显示的页面都是MVVM术语中的一个视图。视图是用于定义和样式化用户所见内容的XAML代码。从模型中获取的数据显示给用户,而ViewModel的工作是根据应用程序的当前状态向UI提供此数据。例如,在图片共享应用中,视图将是向用户显示设备上相册列表、相册中的图片以及可能向用户显示特定图片的UI。

  • ViewModel:ViewModel将数据模型(或简单地说是模型)与应用程序的UI(或视图)绑定。它包含用于管理来自模型的数据并将数据作为一组属性暴露给XAML UI(或视图)的逻辑。例如,在图片共享应用中,ViewModel将公开相册列表,并且对于每个相册,公开图片列表。UI不知道图片来自何处以及如何检索它们。它只知道由ViewModel公开的一组图片,并向用户显示它们。


8
请注意,所引用的文章涉及使用Microsoft Stack开发 - 特别是Windows Phone - 和XAML,但并非必须如此。请注意在翻译过程中不改变原意。 - Richard Nalezynski
4
这个回答强调了“MVVM”这个名称的问题 - 它应该是“VVMM”或“MVMV” - M-V-VM的关系完全颠倒了! - Etherman

55

我认为其中一个主要区别在于,在MVC中,你的V直接读取你的M,并通过C操作数据,而在MVVM中,你的VM作为M代理,同时向你的V提供可用功能。

如果我没有胡说的话,我很惊讶没有人创建一个混合版本,其中你的VM仅是一个M代理,而C提供所有功能。


1
“+1”这个术语是我认为正确的。但是创建混合M-MProxy-V-C隔离层是否有些过度呢?我认为仅使用具有完整绑定支持的模型M作为M-V-C已经足够了。;) - ktutnik
2
+1. 正如我在上面评论中所说,我认为MVC用于设计整个(Web)应用程序,而MVVM则用于MVC的View组件内部。 - Tomasz Zieliński
25
通常模型位于服务器上,而ViewModel存在于客户端。因此,HTML无法直接绑定到服务器端的模型,我们需要ModelView来充当本地未保存的工作数据集,该数据集是通过使用AJAX/JSON从模型中提取的。 - Tomasz Zieliński
1
视图确实“读取”模型数据,因为控制器已经将其放置在那里。我喜欢称之为控制器的“数据注入”,因为它真正负责。在我看来,视图只需要渲染和触发事件。 - JWP
3
抱歉,我对MVVM的解释有所不同。ViewModel并不知道View或View的外观、响应方式,Model同样也不知道ViewModel的存在。实际上,View甚至不应该知道Model的存在,只需知道ViewModel的存在即可。Model应该表示数据和应用程序状态,ViewModel应该将状态转换为UI可用数据(此时我建议使用所有原语类型),而View则应该根据ViewModel的翻译进行反应。数据通常是相同的,但仍应通过ViewModel进行包装和重新传递,不需要任何控制器存在。 - Michael Puckett II

53
其他回答可能不容易理解,对于那些不太熟悉架构模式的人来说。 刚接触应用程序架构的人可能想知道如何选择架构模式会实际影响她的应用程序以及社区中所有的大惊小怪是什么意思。
为了阐明上述问题,我编写了涉及MVVM、MVP和MVC的这个剧本。故事从用户在电影搜索应用程序中点击“查找”按钮开始…:
用户:点击… View: 是谁? [MVVM|MVP|MVC]
用户:我刚刚点击了搜索按钮… View: 好的,请等一下…。[MVVM|MVP|MVC]
View 调用 ViewModel|Presenter|Controller … )[MVVM|MVP|MVC] View: 嘿,ViewModel|Presenter|Controller,一个用户刚刚点击了搜索按钮,我该怎么办?[MVVM|MVP|MVC] ViewModel|Presenter|Controller: 嘿,View,那个页面上有任何搜索词吗? [MVVM|MVP|MVC] View: 是的,这里它是… “钢琴” [MVVMMVP|MVC之间最重要的区别在于此]

Presenter|Controller: 谢谢View,与此同时我正在Model上查找搜索词,请向用户展示进度条。[MVP|MVC]

(Presenter|Controller正在调用Model...) [MVP|MVC]

ViewModel: 谢谢,我将在Model上查找搜索词,但不会直接更新您。相反,如果有任何结果,我将触发searchResultsListObservable的事件。因此,最好在那里观察。[MVVM]

(当观察到searchResultsListObservable中的任何触发器时,View认为应向用户显示一些进度条,因为ViewModel不会直接通知它)

——————————————————————————————

ViewModel|Presenter|Controller: 嘿,Model,你对这个搜索词“piano”有任何匹配吗?[MVVM|MVP|MVC]

Model: 嘿,ViewModel|Presenter|Controller,让我查一下...[MVVM|MVP|MVC]

(Model正在向电影数据库查询...) [MVVM|MVP|MVC]

(过了一会儿...)

———— 这是MVVMMVPMVC的分歧点 ————–

模型:我为你找到了一个列表,视图模型|展示者,这里是它的JSON格式:“[{“name”:”钢琴老师”,”year”:2001},{“name”:”钢琴”,”year”:1993}]” [MVVM|MVP]

模型:有一些结果可以用,控制器。我已经在我的实例中创建了一个字段变量,并将其填充了该结果。它的名称是“searchResultsList” [MVC]

(展示者|控制器感谢模型并返回视图) [MVP|MVC]

展示者:谢谢你等待,视图,我为你找到了一系列匹配的结果,并以一个可呈现的格式排列好了它们:“钢琴老师 2001”、“钢琴 1993”。请现在隐藏进度条 [MVP]

控制器:谢谢你等待,视图,我已经向模型询问了你的搜索查询。它说找到了一系列匹配的结果,并将它们存储在其实例内部的一个名为“searchResultsList”的变量中。你可以从那里获取它。请现在隐藏进度条 [MVC]

视图模型:任何对searchResultsListObservable的观察者都会被通知,有这个新列表以可呈现的格式:“钢琴老师 2001”、“钢琴 1993”。[MVVM]

视图:非常感谢Presenter [MVP]

视图:感谢“控制器” [MVC](现在,视图正在自问:我应该如何向用户呈现从模型得到的结果?电影的生产年份应该排在最前面还是最后面...?)

视图:哦,搜索结果列表中有一个新的触发器......好了,有一个可呈现的列表,现在我只需要将其显示在列表中。既然我已经得到了结果,我也应该隐藏进度条。[MVVM]

如果您感兴趣,我写了一系列文章这里,通过实现一个电影搜索Android应用程序来比较MVVM、MVP和MVC。


4
这里有一个非常棒的答案,所有的口水话除去格式化和组件之间的交谈后,它可以成为本页面上最好的答案。 - neonblitzer
1
讲解得很清楚,并突出了MVC和MVVM之间的根本区别。 - Kedar
到目前为止,这是我找到的最好的解释! - Ahmed Elsayed

43

MVC是受控环境,MVVM是反应性环境。

在受控环境中,代码量应该较少,逻辑的来源应该是通用的。这些都应该位于控制器中。然而,在Web世界中,MVC很容易分成视图创建逻辑和视图动态逻辑两部分。创建逻辑位于服务器上,动态逻辑位于客户端上。例如,在使用ASP.NET MVC和AngularJS时,服务器将创建一个视图并传递一个模型到客户端。客户端将与视图交互,此时AngularJS作为本地控制器介入。提交后,模型或新模型被传回服务器控制器并处理。(因此,当与套接字或AJAX等工作时有很多其他的处理方式,但总体架构相同)

MVVM是一种反应性环境,意味着通常会编写代码(如触发器),以响应某些事件。在XAML中,MVVM繁荣发展,这里可以轻松地使用内置的数据绑定框架完成所有操作,但正如前面提到的,这在任何系统中的任何视图中使用任何编程语言都可以实现。视图模型会触发(通常是属性更改事件),而视图会根据您创建的任何触发器对其进行反应。这可能会变得很技术性,但归根结底,视图是无状态而且没有逻辑的,它只是根据值改变状态。此外,视图模型是无状态的,几乎没有逻辑,而模型则是具有零逻辑的状态,因为它们只应维护状态。我将这描述为应用程序状态(模型),状态转换器(视图模型)以及视觉状态/交互(视图)。

在MVC桌面或客户端应用程序中,应该有一个模型,并且控制器应该使用该模型。基于模型,控制器将修改视图。视图通常使用接口与控制器相连,以便控制器可以与各种视图一起使用。在ASP.NET中,MVC的逻辑略微倒置,因为控制器管理模型并将模型传递给选定的视图。然后,视图根据模型填充数据并具有自己的逻辑(通常是另一个MVC集,例如AngularJS)。人们会争论并混淆这个问题,试图同时做两件事,此时维护项目最终会变成一场灾难。当使用MVC时,始终将逻辑和控制放在一个位置上。不要在视图的代码后台(或通过Web中的JS视图)中编写视图逻辑以适应控制器或模型数据。让控制器改变视图。唯一应该存在于视图中的逻辑是所需接口的创建和运行。例如,提交用户名和密码。无论是桌面还是Web页面(在客户端),控制器都应处理提交过程,每当视图触发提交操作时。如果做得正确,您始终可以轻松地找到MVC Web或本地应用程序的方法。

MVVM是我个人最喜欢的模式,因为它完全是响应式的。如果Model状态发生变化,ViewModel会监听并翻译该状态,然后View会根据来自ViewModel的翻译进行更新。有些人称之为纯MVVM,但实际上只有一种MVVM,我不在乎你怎么争辩,而且它始终是纯MVVM,其中View不包含任何逻辑。
以下是一个简单的例子:假设您想在按钮按下时滑动菜单。在MVC中,您将在接口中拥有一个MenuPressed操作。控制器将知道您点击了Menu按钮,然后告诉View基于另一个接口方法SlideMenuIn滑入菜单。一个往返,有什么必要吗?以防万一Controller决定您不能这样做或者希望做其他事情。Controller应该负责View,除非Controller说了算,否则View什么都不做。然而,在MVVM中,滑入菜单动画应该是内置和通用的,而不是被告知要滑入时才执行。因此,它会听取ViewModel,当ViewModel说IsMenuActive=true(或其他)时,就会执行该操作的动画。现在,话虽如此,我想再强调一点,请注意。IsMenuActive可能是错误的MVVM或ViewModel设计。当设计ViewModel时,您不应该假设View将拥有任何功能,只需传递翻译后的Model状态即可。这样,如果您决定更改View以删除菜单并以其他方式显示数据/选项,ViewModel也不会关心。那么,要如何管理菜单呢?当数据有意义的时候就可以。因此,一种方法是给菜单一个选项列表(可能是一些内部ViewModel的数组)。如果该列表具有数据,则菜单通过触发器知道要打开,如果没有数据,则菜单通过触发器知道要隐藏。您只需在ViewModel中拥有菜单或无菜单的数据即可。不要在ViewModel中决定显示/隐藏该数据。仅翻译Model的状态即可。这样,View就完全是响应式和通用化的,并且可以在许多不同的情况下使用。
如果您对每种架构都有至少基础的了解,那么所有这些可能完全没有意义,学习它可能会非常令人困惑,因为你会发现网络上有很多错误的信息。
因此...要正确掌握这些,请记住几件事情。事先决定如何设计应用程序,并坚持不变。如果您使用MVC,那太好了,请确保您的控制器(Controller)是可管理的,完全掌控您的视图(View)。 如果您有一个大的视图,则考虑向其添加具有不同控制器的控件。但是请勿将这些控制器级联到不同的控制器中。这样很难维护。花点时间以一种可作为单独组件工作的方式分别设计事物...并始终让控制器(Controller)告诉模型(Model)提交或持久化存储。 MVC的理想依赖设置为 View ← Controller → Model 或者在ASP.NET中(不要让我开始)Model ← View ↔ Controller → Model (其中Model可以从Controller到View是相同的或完全不同的)...当然,此时在View中只需要知道Controller以进行端点引用,以了解返回Model的位置。
如果您使用MVVM,祝您幸运,请花时间正确地做。首先不要使用接口。让您的View根据值决定其外观。使用Mock数据测试View。如果您最终获得的View正在显示菜单(如示例所示),即使您当时不想要它,那么很好。你的View正在按照应该的方式进行工作,并根据值进行反应。只需添加几个其他要求来触发,以确保在ViewModel处于特定的翻译状态时不会发生这种情况,或者命令ViewModel清空此状态。在您的ViewModel中,请勿使用内部逻辑来删除此内容,因为您正在从那里决定View是否应看到它。请记住,您不能假定ViewModel中有菜单项或没有。最后,Model只应允许您更改和存储状态。例如,如果Model无法修改状态,则它将简单地标记自己为脏状态。当ViewModel意识到这一点时,它将翻译出“脏”的信息,View将意识到这一点并通过另一个触发器显示一些信息。视图中的所有数据都可以绑定到ViewModel,因此一切都可以是动态的,只有Model和ViewModel根本不知道View将如何对绑定做出反应。实际上,Model甚至不知道ViewModel。在设置依赖关系时,它们应该指向 View→ViewModel→Model(这里还有一个注意事项...这可能也会引起争论,但我不在乎...除非该MODEL是不可变的,否则不要将MODEL传递给VIEW;否则,请使用正确的ViewModel进行包装。View不应该看到模型。我不管你看到过哪个演示或者你如何做,这都是错误的)。
这是我的最后一条提示...查看设计良好但非常简单的MVC应用程序,并对MVVM应用程序执行相同的操作。一个将具有受限但可控制的灵活性,而另一个则没有控制而无限制的灵活性。

控制环境适合通过一组控制器或(单个来源)管理整个应用程序,而反应性环境可以分为不同的存储库,完全不知道应用程序的其余部分正在做什么。微观管理与自由管理。

如果我还没有让你感到困惑,请联系我...我不介意详细说明并提供插图和实例。

归根结底,我们都是程序员,在编码时会存在无政府主义...因此规则会被打破,理论会改变,所有这些最终都将变得毫无意义...但是在处理大型项目和大型团队时,确实有助于达成设计模式一致并强制执行。某一天,初期采取的小额外步骤将使节省成本跨越巨大的进展。


3
非常详细和准确的答案!使我完全明白了。 :-) - ankush981
2
学习编程可能会非常困惑,因为你会在网上找到很多错误的信息。是的,作为一个似乎有很多设计模式经验的人,你知道有哪些好的教程/指南吗? - MarredCheese
2
说实话,我的MVVM知识是经过多年的尝试和错误以及基于团队努力使用/实践出来的。最近(2年前),我能够将自己的经验总结成一个游戏计划并带领团队从头到尾完成,我们取得了极大的成功。话虽如此,我不能指向任何一个地方并道歉。我可以说你是正确的,因为由于各种不同的意见,它非常令人困惑,但在我看来,MVVM需要尽可能地通用。使ViewModels能够让视图严格绑定和处理数据,但适用于任何视图… - Michael Puckett II
2
换句话说,ViewModel 绝不能假设 View 的外观或行为。对我来说,ViewModel 最好像一个带有严格通信的 API。遵循绑定、编辑、命令等方面的计划。如果 View 需要额外的逻辑以特定方式运行,那么这与应用程序或数据无关(例如动画或下拉框),则该逻辑属于 View 层的某个位置。再次强调,有大量不同的意见,这只是我的意见,但我在这方面拥有坚实的背景和可靠的记录。 - Michael Puckett II
1
我有一些示例应用程序,愿意分享,并且如果您想要或感兴趣的话,我也很乐意为您或其他人设置一个简单的展示和讲解。 - Michael Puckett II
显示剩余2条评论

34

简单区别:(受Yaakov的Coursera AngularJS课程启发)

enter image description here

MVC(模型视图控制器)

  1. 模型:包含数据信息。不调用或使用控制器和视图。包含业务逻辑和表示数据的方式。其中一些数据可能以某种形式显示在视图中。它也可以包含检索数据的逻辑。
  2. 控制器:作为视图和模型之间的连接。视图调用控制器,控制器调用模型。基本上,它会根据需要通知模型和/或视图进行更改。
  3. 视图:处理UI部分。与用户交互。

MVVM(模型视图视图模型)

ViewModel:

  1. 它是视图状态的表示。
  2. 它保存在视图中显示的数据。
  3. 响应视图事件,即表示逻辑。
  4. 调用其他功能以进行业务逻辑处理。
  5. 永远不会直接要求视图显示任何东西。

19

MVVM是Presentation Model模式的一种改进(有争议)。我说有争议,因为唯一的区别在于WPF提供了数据绑定和命令处理的能力。


2
在2009年,这个答案可能是正确的,但是今天,没有争议,因为即使是来自MSFT的HTML Helper控件也允许使用臭名昭著的“For”助手进行绑定。 Knockout完全是关于客户端数据绑定的。 - JWP
2
我在2009年提出了这个观点,因为社区中有太多人接受了这个答案。我说这是有争议的,因为MVVM和Presentation Model实际上是不同名称的相同模式。由于在WPF中的流行,它今天在其他框架中通常被称为MVVM,但两个名称都是准确的。 - wekempf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接