MVC和MVVM有什么区别?[关闭]


1312

标准“模型视图控制器”模式和Microsoft的Model / View / ViewModel模式之间有区别吗?


54
请注意,虽然MVVM是由Microsoft创造的,但许多非Microsoft开发人员和项目已开始采用这种模式。此评论是由讨厌的MS部门提供给您的。
BoltClock

1
在MVVM上工作了很长时间之后,我对MVC的第一次使用感到沮丧,直到我得知我可以使用MVVM中的绑定技术将ViewModels来回传递给浏览器。但是正如Joel所说的那样,从浏览器获取状态的唯一方法是将更改以表单(使用名称/值)对的形式发布。如果您不明白这一点。您在MVC中会遇到困难。只需将控制器视为视图的依赖项注入器即可,一切就绪。
约翰·彼得斯2014年

2
对高级[设计模式]提出了这样的质疑。我想建议在答案上使用图表。
里卡多2015年


1
与MVC方法不同,ViewModel不是控制器。相反,它充当在视图和模型之间绑定数据的绑定器。MVC格式是专门为在模型和视图之间建立关注点而设计的,而具有数据绑定的MVVM格式是专门为允许视图和模型彼此直接通信而设计的。hackernoon.com/...
blueray

Answers:


684

MVC / MVVM是不是一个非此即彼/或选择。

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

对于ASP.Net,MVVM用于在视图内双向绑定数据。这通常是客户端实现(例如,使用Knockout.js)。另一方面,MVC是一种在服务器端分离问题的方法。

对于Silverlight和WPF,MVVM模式更具涵盖性,并且似乎可以替代MVC(或将软件组织成单独职责的其他模式)。一个假设,经常来到这个模式中出来,是,ViewModel简单地更换控制器MVC(如如果你可以只替换VMC的缩写,所有会原谅)...

该视图模型并没有必然代替单独控制器的需求。

问题是:要独立测试*,尤其是在需要时可重用,则视图模型不知道显示哪个视图,更重要的是不知道其数据来自何处

*注意:实际上,控制器从ViewModel中删除了需要进行单元测试的大多数逻辑。然后,VM成为一个哑容器,几乎不需要测试。这是一件好事,因为VM只是设计人员和编码人员之间的桥梁,因此应保持简单。

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

到目前为止,我们已经看到ViewModel模式的主要好处是可以从XAML代码背后删除代码,从而使XAML编辑成为更加独立的任务。我们仍然会根据需要创建控制器,以控制(无双关语)应用程序的整体逻辑。

我们遵循的基本MVCVM准则是:

  • 视图显示某种形状的数据。他们不知道数据来自哪里。
  • ViewModels 具有某种形状的数据和命令,它们不知道数据或代码来自何处或如何显示。
  • 模型保存实际数据(各种上下文,存储或其他方法)
  • 控制器侦听并发布事件。控制器提供了控制哪些数据可以看到以及在何处的逻辑。控制器将命令代码提供给ViewModel,以便ViewModel实际上可重用。

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

不要以为视图模型会使控制器过时。

我已经开始撰写有关此主题的博客,并将在可能的时候添加到该博客中。将MVCVM与常见的导航系统结合存在问题,因为大多数导航系统仅使用Views和VM,但是我将在以后的文章中进行介绍。

使用MVCVM模型的另一个好处是,在应用程序的生命周期内仅控制器对象需要存在于内存中,并且控制器主要包含代码和少量状态数据(即,很小的内存开销)。与必须保留视图模型的解决方案相比,这使应用程序占用的内存少得多,并且它对于某些类型的移动开发(例如,使用Silverlight / Prism / MEF的Windows Mobile)非常理想。当然,这确实取决于应用程序的类型,因为您可能仍需要保留偶尔缓存的VM以提高响应能力。

注意:这篇文章已经过多次编辑,并且没有专门针对所提出的狭窄问题,因此我也更新了第一部分,现在也涵盖了这一部分。在下面的评论中,许多讨论仅涉及ASP.Net,而不涉及更广泛的情况。这篇文章旨在涵盖MVVM在Silverlight,WPF和ASP.Net中的更广泛使用,并试图劝阻人们不要使用ViewModels替换控制器。


8
@Tomasz Zielinski:是的,但是“问题所在”不是问题所在(也不是我回答的重点)。我的观点是,控制器在MVVM中仍然有用。
Gone Coding,

58
我同意。我的评论是突然的开悟引起的,而不是因为我不同意你的看法。
TomaszZieliński

我们还使用控制器来控制类似向导的UI中的视图“流”。
riezebosch 2012年

3
@贾斯汀:我看到那句话的措词有点含糊。实际上,我的意思是更容易支持所有组件的单元测试,而不仅仅是改善ViewModels的测试(正如您所指出的那样,在MVCVM中实际上并没有做太多……这就是您想要的)。控制器的真正好处是,您实际上从ViewModel中删除了大多数测试需求(人们一直在推销控制器逻辑),并将其放置在可以测试的地方(主要是Controllers和Models)。重用注释特定于该句中的VM。我已经编辑了。
Gone Coding

7
@TomaszZielinski M(MVVM)C
Mohamed Emad

273

我认为理解这些首字母缩略词含义的最简单方法是暂时忘记它们。取而代之的是,考虑一下它们起源的软件。实际上,可以归结为早期Web和桌面之间的区别。

随着它们在2000年代中期的复杂性增长,MVC软件设计模式-1970年代首次被描述-开始应用于Web应用程序。考虑数据库,HTML页面和它们之间的代码。让我们对其进行细化以得出MVC:对于»database«,我们假设数据库加上接口代码。对于“ HTML页面”,我们假设HTML模板加上模板处理代码。对于“之间的代码”,我们假设代码将用户的点击映射到操作,这可能会影响数据库,从而肯定会显示另一个视图。就是这样,至少出于此比较的目的。

让我们保留该Web东西的一个功能,而不是今天,而是十年前存在的那年,当时JavaScript是一种卑鄙的,令人卑鄙的烦恼,真正的程序员对此很好地避免了:HTML页面本质上是愚蠢而被动的。浏览器是瘦客户端,或者如果可以的话,它是不良客户端。浏览器中没有智能。整页重新加载规则。每次都会重新生成»view«。

让我们记住,尽管风靡一时,但与台式机相比,这种Web方式仍然落后很多。桌面应用程序可以是胖客户端,也可以是富客户端。(甚至可以将Microsoft Word之类的程序视为某种类型的客户端,即文档的客户端。)它们是充满智能,对数据知识丰富的客户端。他们是有状态的。他们将正在处理的数据缓存在内存中。没有像整页重新加载这样的废话。

这种丰富的桌面方式可能就是第二个缩写MVVM的起源。不要被字母所迷惑,不要被C所迷惑。控制器仍然在那里。他们必须是。什么都不会去除。我们只添加一件事:状态性,缓存在客户端上的数据(以及用于处理该数据的智能)。该数据实际上是客户端上的缓存,现在称为»ViewModel«。这就是允许丰富交互性的原因。就是这样。

  • MVC =模型,控制器,视图=本质上是单向通信=交互性较差
  • MVVM =模型,控制器,缓存,视图=双向通信=丰富的交互性

我们可以看到,借助Flash,Silverlight和最重要的JavaScript,Web已包含了MVVM。浏览器不再可以合法地称为瘦客户端。看他们的可编程性。看他们的内存消耗。查看现代网页​​上的所有Javascript交互性。

我个人认为,通过查看具体现实中所指的内容,该理论和首字母缩写词业务更容易理解。抽象的概念很有用,尤其是在具体问题上进行演示时,这样的理解可能会绕一圈。

 


47
MVC并非起源于网络。Trygve Reenskaug在1970年代将MVC引入Smalltalk-76。
2014年

11
即使更改为“ MVC通过Web应用程序设计进行了普及”。我认为这是没有适当引用的推测。
丹·贝查德

4
Arialdo:谢谢,我不了解Smalltalk-76。(当时和其他玩具一起玩过。:)开个玩笑,有趣的是这些概念有多古老了。-@Dan,我写的是:“ [MVC]可能在[Web]之前就出现过,但是Web是如何被大众化的Web开发人员的。” 我仍然认为是正确的。我没有引用它,但是后来我觉得我不需要,因为当我在上个十年初开始作为Web开发人员时,MVC的大规模普及是我个人经验的一部分。那时,Apache Struts一直风靡一时,它为MVC提供了很多bean。
卢米2014年

5
MVC并非“本质上是单向通信”,因为浏览器始终会发出“获取和发送”消息。获取和发布都可以更改在查询字符串中找到的字段值。这使浏览器有足够的机会将信息发送回控制器。MVC建立在HTTP 1.0之上,HTTP 1.0始终牢记两种通信方式。
约翰·彼得斯

13
谢谢Lumi。这对我来说比其他答案更有意义。这是对的吗?我不知道。但是从我的角度来看,这至少是连贯的。
gcdev 2015年

175

MVVM Model-View ViewModel与MVC,Model-View Controller类似

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

Russel East在博客上详细讨论了 为什么MVVM与MVC不同


81
句子“用视图模型替换控制器”是不正确的。在MVVM中,控制器的作用是数据绑定(如果使用绑定,则按惯例绑定)。
DaniCE 2010年

9
MVVM仅在使用WPF的双向数据绑定时才有意义。否则,MVC / MVP等就足够了。
杰夫2010年

265
@DaniCE:乔什·史密斯:If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions. …
sll

7
@OmShankar 11号不是你自己。总共有10人,共有12条意见。这句谚语的意思是,这些模式的定义易于解释,以至于至少有两个人会被混淆以至于不只一种意见。
丹·贝查德

7
@DaniCE好吧,这实际上是WPF数据绑定的重点,并且Microsoft发明了MVVM,因为它可以完全绕过控制器,(声称语句“正在用视图模型替换控制器”是不正确的,因为幕后的控制器,基本上就像是声称“高级语言以更易读的语言代替使用加密的机器代码”的说法是不正确的,因为幕后的机器语言仍在使用...)
yoel halb

91

一方面,MVVM是MVC模式的演进,该模式使用XAML来处理显示。 本文概述了两者的某些方面。

Model / View / ViewModel体系结构的主要目的似乎是在数据之上(“模型”),还有另一层非可视组件(“ ViewModel”),它们更紧密地映射了数据的概念数据视图(“视图”)的概念。视图绑定到的是ViewModel,而不是直接绑定到Model。


20
我认为您引用的段落很好地总结了恕我直言。ViewModel的一个方面是它是视图模型的扁平/更改版本。许多其他MV *模式与实际模型绑定在一起。
Daniel Auger

1
??“许多其他MV *模式绑定再次真实模型”真的我想的观点总是应该绑定到MVC控制器,不管是什么。
PlagueHammer

9
夜曲:在经典的MVC中,View与控制器没有多大关系,它主要绑定到Model。可以将其视为机器人-模型代表机器人关节的位置,View是您可以看到机器人的LCD监视器,Controller是例如键盘。在这种设置中,视图取决于模型,即您可以在监视器上看到的机器人的空间位置是模型的直接表示。
TomaszZieliński

@Nocturne丹尼尔似乎在说,虽然所有的MV *都应该使用单独的VM,但许多开发人员只是忽略了它,并传递了实际的模型,实际上,例如MVC的规范中都没有禁止它,但是在MVVM中虚拟机必须负责模型和视图之间的过渡
yoel halb 2014年

我会这样说:模型是DB模式的壁橱。运行查询时,它可以在模型层将数据投影为强类型。视图模型是事物的集合,包括模型对象,但是可以并且确实保存关于数据的视图状态。控制器只是视图模型和视图之间的交通警察,当然视图仅与视图状态有关。
约翰·彼得斯2014年

52

Microsoft 在此处提供了Windows环境中MVVM模式的说明

这是关键部分:

在Model-View-ViewModel设计模式中,一个应用程序由三个常规组件组成。 在此处输入图片说明

  • 模型:这表示您的应用程序使用的数据模型。例如,在图片共享应用中,该层可能表示设备上可用的图片集以及用于读取和写入图片库的API。

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

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


7
请注意,虽然所引用的文章适用于使用Microsoft Stack(特别是Windows Phone)和XAML进行开发,但并非必须如此。
理查德·纳雷辛斯基

这个答案突出了名称“ MVVM”的问题-应该是“ VVMM”或“ MVMV”-MV-VM的关系完全错误!
以太曼

45

我认为主要区别之一是在MVC中,您的V直接读取您的M,然后通过C来操作数据,而在MVVM中,您的VM充当M代理,并为您提供可用功能V.

如果我还没装满垃圾,我会惊讶的是没有人创建一个混合服务器,其中您的VM只是一个M代理,而C提供了所有功能。


1
+1。这个词是我认为正确的词。但是关于创建混合M-MProxy-VC并不是有太多分离吗?我认为使用MVC就足够了,而M是完全支持Binding的Model。;)
ktutnik 2010年

2
+1。如上所述,我认为MVC用于构建整个(Web)应用程序,而MVVM用于MVC的View组件内部。
TomaszZieliński

23
@ktutnik:模型通常位于服务器上,而ViewModel位于客户端上。因此,将HTML直接绑定到服务器端模型是不可行的。因此,我们需要ModelView,它充当使用例如AJAX / JSON从模型中提取的本地未保存工作数据集。
TomaszZieliński

1
该视图的确确实“读取”了模型数据,因为控制器已经将其放置在那里。我喜欢将其称为控制器的“数据注入”,因为它实际上是由控制器负责的。所有视图都在我脑海中进行渲染和触发事件。
约翰·彼得斯

3
我很抱歉,但不同意MVVM的解释。ViewModel不了解View,也不了解View的外观或响应方式,而Model同样也不了解ViewModel。实际上,View甚至都不应该知道模型,而只是ViewModel。模型应该代表数据和应用程序状态,ViewModel应该将状态转换为支持UI的数据(我建议此时使用所有原语),而View应该对ViewModels转换做出反应。数据通常是相同的,但仍应通过ViewModel进行包装和重新传递,并且不存在任何控制器。
Michael Puckett II

23

简单差异:(受Yaakov的Coursera AngularJS课程启发)

在此处输入图片说明

MVC(模型视图控制器)

  1. 模型:模型包含数据信息。不调用或使用Controller和View。包含业务逻辑和表示数据的方式。某些数据可能以某种形式显示在视图中。它还可以包含从某些来源检索数据的逻辑。
  2. 控制器:充当视图和模型之间的连接。查看调用Controller和Controller调用模型。它基本上通知模型和/或视图适当地更改。
  3. 视图:处理UI部分。与用户互动。

MVVM(模型视图视图模型)

ViewModel

  1. 它是视图状态的表示。
  2. 它保存在视图中显示的数据。
  3. 响应查看事件,也称为表示逻辑。
  4. 调用其他功能进行业务逻辑处理。
  5. 切勿直接要求视图显示任何内容。

23

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

在受控的环境中,您应该减少代码并使用通用的逻辑源。它应该始终存在于控制器中。然而; 在网络世界中,MVC容易分为视图创建逻辑和视图动态逻辑。创建生活在服务器上,动态生活在客户端上。通过将ASP.NET MVC与AngularJS结合使用,您会看到很多东西,而服务器将创建一个View并传递一个Model并将其发送给客户端。然后,客户端将与View交互,在这种情况下,AngularJS将作为本地控制器进入。提交模型后,会将新模型或新模型传递回服务器控制器并进行处理。(因此,循环继续进行,使用套接字或AJAX等时,此处理还有很多其他转换,但是在整个体系结构上都是相同的。)

MVVM是一种反应性环境,这意味着您通常会编写将基于某些事件激活的代码(例如触发器)。在MVVM蓬勃发展的XAML中,这一切都可以通过内置的数据绑定框架BUT轻松完成,如上所述,它可以在具有任何编程语言的任何View的任何系统上运行。它不是特定于MS的。ViewModel触发(通常是一个属性更改事件),并且View根据您创建的任何触发器对其作出反应。这可以提高技术性,但最重要的是View是无状态的,没有逻辑。它只是根据值更改状态。此外,ViewModels是无状态的,逻辑很少,而Models是状态,其逻辑基本上为零,因为它们只应保持状态。我将其描述为应用程序状态(模型),状态转换器(ViewModel),然后是可视状态/交互(视图)。

在MVC桌面或客户端应用程序中,您应该有一个Model,并且Controller应该使用该Model。控制器将基于模型修改视图。视图通常与带有接口的控制器绑定在一起,以便控制器可以使用各种视图。在ASP.NET中,由于Controller管理模型并将模型传递到选定的视图,因此MVC的逻辑在服务器上稍微向后倾斜。然后,视图会根据模型填充数据,并具有自己的逻辑(通常是另一个MVC集,例如使用AngularJS完成的设置)。人们会争论不休,并将其与应用程序MVC混淆,然后尝试同时做这两个事情,这时维护项目最终将成为灾难。使用MVC时,始终将逻辑和控制放在一个位置。不要在View后面的代码中(或在通过JS for web的View中)编写View逻辑以容纳Controller或Model数据。让控制器更改视图。通过它所使用的接口创建和运行视图所需的一切只是逻辑。例如,提交用户名和密码。无论是桌面还是网页(在客户端上),只要View触发了Submit操作,Controller都应处理提交过程。如果做得正确,您总是可以轻松地在MVC网站或本地应用中找到自己的出路。无论是桌面还是网页(在客户端上),只要View触发了Submit操作,Controller都应处理提交过程。如果做得正确,您总是可以轻松地在MVC网站或本地应用中找到自己的出路。无论是桌面还是网页(在客户端上),只要View触发了Submit操作,Controller都应处理提交过程。如果做得正确,您总是可以轻松地在MVC网站或本地应用中找到自己的出路。

我个人最喜欢MVVM,因为它具有完全的反应性。如果Model更改了状态,则ViewModel会侦听并转换该状态,仅此而已!!!然后,视图正在侦听ViewModel的状态更改,并且它还会根据ViewModel的转换进行更新。有人将其称为纯MVVM,但实际上只有一个,我不在乎您如何争论它,而它始终是纯MVVM,其中View完全不包含逻辑。

这是一个小例子:假设您想在按下按钮时插入菜单幻灯片。在MVC中,您的界面中将具有MenuPressed操作。当您单击“菜单”按钮,然后告诉视图基于其他接口方法(例如SlideMenuIn)在菜单中滑动时,控制器将知道。往返是出于什么原因?如果控制器决定您不能执行或要执行其他操作,这就是原因。控制器应负责视图,而视图则不执行任何操作,除非控制器如此说。然而; 在MVVM中,动画的幻灯片菜单应该是内置的并且是通用的,而不是被告知要在其中滑动幻灯片,而是基于某些值。因此,它侦听ViewModel,并且当ViewModel说IsMenuActive = true时(或者,发生动画)。现在,我要说的是另一点,确实要清除,请注意。IsMenuActive可能是BAD MVVM或ViewModel设计的。设计ViewModel时,您永远不应假定View完全具有任何功能,而只需传递已转换的模型状态即可。这样,如果您决定更改视图以删除菜单,而仅以另一种方式显示数据/选项,则ViewModel不在乎。那么,您将如何管理菜单?当数据有意义时,就是这样。因此,执行此操作的一种方法是为Menu提供选项列表(可能是内部ViewModel的数组)。如果该列表中有数据,则菜单会通过触发器知道打开,否则就知道会通过触发器隐藏。您只是在菜单中有数据,还是在ViewModel中没有。不要决定在ViewModel中显示/隐藏该数据。只需翻译模型的状态。这样,视图就完全是被动的和通用的,并且可以在许多不同的情况下使用。

如果您还没有至少略微熟悉每种体系结构,并且由于在网络上会发现大量的不良信息而对它们的学习感到非常困惑,那么所有这些都可能毫无意义。

所以...为了正确起见,请记住一些事情。预先确定如何设计应用程序并坚持下去。

如果您做MVC,这很棒,那么请确保Controller是可管理的,并且完全控制View。如果您的View很大,请考虑向具有不同Controller的View添加控件。只是不要将那些控制器级联为不同的控制器。维护非常令人沮丧。花一点时间,以一种可以作为单独的组件工作的方式分别设计事物,并始终让Controller告诉模型提交或持久存储。MVC的理想依赖项设置是View←Controller→Model 或使用ASP.NET(不让我开始)Model←View↔Controller→Model(其中,从Controller到View的Model可以相同或完全不同)...当然,此时,唯一需要了解View中的Controller的地方主要是供端点参考来了解将模型传递回何处。

如果您使用MVVM,我会祝福您的良心,但是花点时间做对吧!请勿将接口用于其中之一。让您的View根据值决定外观。播放“模拟视图”数据。如果您最终拥有一个显示菜单的视图(按照示例),即使您当时不想要它,也可以选择“好”。您认为视图正在按其应有的方式工作,并根据应有的值做出反应。只需向触发器添加更多要求,以确保在ViewModel处于特定转换状态时不会发生这种情况,或命令ViewModel清空此状态。在您的ViewModel中,请勿使用内部逻辑删除它,就像您要从那里确定View是否应该看到它一样。请记住,您不能假定ViewModel中没有菜单。最后,该模型应该只允许您更改和最可能的存储状态。这是验证的地方,所有都会发生。例如,如果模型无法修改状态,那么它将简单地将自身标记为脏或类似状态。当ViewModel意识到这一点时,它将翻译脏的内容,然后View将意识到这一点并通过另一个触发器显示一些信息。View中的所有数据都可以绑定到ViewModel,因此一切都是动态的,只有Model和ViewModel完全不知道View如何对绑定做出反应。实际上,模型也不知道ViewModel。设置依赖项时,它们应该这样指向并且仅这样指向 t修改状态,然后它会简单地将自己标记为脏或其他内容。当ViewModel意识到这一点时,它将翻译脏的内容,然后View将意识到这一点并通过另一个触发器显示一些信息。View中的所有数据都可以绑定到ViewModel,因此一切都是动态的,只有Model和ViewModel完全不知道View如何对绑定做出反应。实际上,模型也不知道ViewModel。设置依赖项时,它们应该这样指向并且仅这样指向 t修改状态,然后它会简单地将自己标记为脏或其他内容。当ViewModel意识到这一点时,它将翻译脏的内容,然后View将意识到这一点并通过另一个触发器显示一些信息。View中的所有数据都可以绑定到ViewModel,因此一切都是动态的,只有Model和ViewModel完全不知道View如何对绑定做出反应。实际上,模型也不知道ViewModel。设置依赖项时,它们应该这样指向并且仅这样指向 View中的所有数据都可以绑定到ViewModel,因此一切都是动态的,只有Model和ViewModel完全不知道View如何对绑定做出反应。实际上,模型也不知道ViewModel。设置依赖项时,它们应该这样指向并且仅这样指向 View中的所有数据都可以绑定到ViewModel,因此一切都是动态的,只有Model和ViewModel完全不知道View如何对绑定做出反应。实际上,模型也不知道ViewModel。设置依赖项时,它们应该这样指向并且仅这样指向视图→视图模型→模型 (以及此处的注释...这可能也会引起争议,但我不在乎...除非模型是不可变的,否则请勿将模型传递给视图;否则将其包装为正确的ViewModel。View不应看到模型周期。我让老鼠破解您所看到的演示或您如何完成的演示,这是错误的。)

这是我的最后一个提示...看一个设计良好但非常简单的MVC应用程序,并对MVVM应用程序执行相同的操作。一个将具有更大的控制权,而灵活性则限于零,而另一个将没有控制权和无限的灵活性。

受控环境非常适合从一组控制器或(单个来源)管理整个应用程序,而反应性环境却可以分解为单独的存储库,而完全不知道应用程序的其余部分在做什么。微管理与免费管理。

如果我对您还没有足够的困惑,请尝试与我联系。。。我不介意通过插图和示例详细介绍这一点。

归根结底,我们都是程序员,编码时无政府状态仍然存在。所以规则将被破坏,理论将发生变化,所有这些最终都会被猪吞噬...但是当从事大型工作时项目和大型团队,这确实有助于达成设计模式并加以实施。有一天,它将使一开始采取的额外小步骤成为节省开支的突飞猛进。


惊人的详细和准确的答案!对我来说非常清晰。:-)
ankush981 '18

“学习它可能会非常令人困惑,因为您会在网上找到很多不良信息。” 是的 作为一个似乎对这些设计模式有丰富经验的人,您知道任何好的教程/指南吗?
MarredCheese

1
老实说,我的MVVM知识已经经历了数年或反复试验,并根据团队的努力以多种方式使用/完成。我最近(2年前)能够将自己的经验纳入一个概括的游戏计划中,并带领团队开始完成这项工作,我们取得了巨大的成功。就是说,我无法指出您的任何歉意。我可以说您是正确的,因为存在各种各样的意见,这非常令人困惑,但是IMO与MVVM应当尽可能通用。使ViewModels能够严格允许视图绑定并使用数据,但对于任何视图都无法使用...
Michael Puckett II

1
换句话说,永远不要使ViewModel假定View将以任何方式外观或动作。对我而言,ViewModel最好像API一样使用,但要进行严格的通信。遵循游戏计划进行绑定,编辑,命令等操作。如果View需要额外的逻辑来实现特定的功能,则与应用或数据(例如动画或下拉框)无关。在某种程度上属于View层。再说一次,有很多意见,这只是我的看法,但我在这里有很强的背景,并且迄今为止有良好的往绩。
Michael Puckett II

我有一些示例应用程序,它们我不介意共享,或者不介意设置一个简单的节目,并告诉您或其他任何想要或好奇的人。
Michael Puckett II

18

MVVM是Presentation Model模式的改进(值得商de)。我说有争议,因为唯一的区别是WPF如何提供执行数据绑定和命令处理的能力。


1
在2009年,这个答案可能是一个不错的答案,但是今天,没有争议,因为即使MSFT的HTML Helper控件也允许使用臭名昭著的“ For”助手进行绑定。淘汰赛只与客户端上的数据绑定有关。
约翰·彼得斯

1
我之所以这么说是在2009年,因为社区中有太多人接受了这个答案。我说这值得商,,因为MVVM和Presentation Model实际上是相同的模式,只是名称不同。与WPF的流行背道而驰,在当今的其他框架中通常将其称为MVVM,但这两个名称都是准确的。
wekempf

15

viewmodel是用户界面元素的“抽象”模型。它必须允许您以非可视的方式执行命令和视图中的操作(例如,对其进行测试)。

如果您使用过MVC,则可能有时发现创建模型对象以反映视图状态非常有用,例如,显示和隐藏一些编辑对话框等。在这种情况下,您正在使用viewmodel。

MVVM模式只是该实践对所有UI元素的概括。

而且这不是Microsoft模式,但要补充的是WPF / Silverlight数据绑定特别适合于使用此模式。但是,例如,没有什么可以阻止您在Java服务器界面上使用它。


13

对于不太熟悉建筑模式主题的人,其他答案可能不容易理解。应用架构的新手可能想知道它的选择如何在实践中影响她的应用,以及社区中所有的大惊小怪。

为了阐明上述内容,我制作了涉及MVVM,MVP和MVC的编剧。故事始于用户单击电影搜索应用程序中的“查找”按钮……:

用户:单击…

视图:那是谁?[ MVVM | MVP | MVC ]

用户:我只是点击了搜索按钮...

视图:好的,稍等片刻……。[ MVVM | MVP | MVC ]

视图正在调用ViewModel | Presenter | Controller …)[ MVVM | MVP | MVC ]

查看:嘿ViewModel | 主持人 | 控制器,一个用户刚刚单击搜索按钮,我该怎么办?[ MVVM | MVP | MVC ]

ViewModel | 主持人 | 控制器:嘿查看,是否有任何网页上的搜索字词?[ MVVM | MVP | MVC ]

视图:是的,这里是…“钢琴” [ MVVM | MVP | MVC ]

-这是MVVMMVP之间最重要的区别| MVC ———

主持人:感谢View,…同时我正在模型上查找搜索词,请向他/她显示进度条[ MVP | MVC ]

演示者 | 控制器正在调用模型 …)[ MVP | MVC ]

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

(在观察searchResultsListObservable中的任何触发器时,View认为它应该向用户显示一些进度条,因为ViewModel不会对此进行交谈)

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

ViewModel | 主持人 | 管理员:嗨,模特儿,您对此搜索词有任何匹配吗?:“ piano” [ MVVM | MVP | MVC ]

模特:嘿ViewModel | 主持人 | 控制器,让我检查一下... [ MVVM | MVP | MVC ]

模型正在查询电影数据库……)[ MVVM | MVP | MVC ]

( 过了一会儿 … )

----这是之间的分歧点MVVMMVPMVC -----

型号:我为您找到了一个列表,ViewModel | 演示者,此处为JSON“ [{{name”:“ Piano Teacher”,“ year”:2001},{“ name”:“ Piano”,“ year”:1993}]]” [ MVVM | MVP ]

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

演示者 | 控制器感谢模型并回到视图)[ MVP | MVC ]

演示者:感谢View的等待,我为您找到了一个匹配的结果列表,并以合适的格式进行排列:[“ Piano Teacher 2001”,“ Piano 1993”]。另外,请立即隐藏进度栏[ MVP ]

控制器:感谢您等待View,我已向Model询问您的搜索查询。它说已经找到了匹配结果的列表,并将它们存储在其实例内部的名为“ searchResultsList”的变量中。您可以从那里得到它。还请现在隐藏进度条[ MVC ]

ViewModel:通知searchResultsListObservable上的任何观察者,该列表以可呈现的格式出现:[“ Piano Teacher 2001”,“ Piano 1993”]。[ MVVM ]

视图:非常感谢主持人[ MVP ]

视图:谢谢“ 控制器 ” [ MVC ](现在视图正在质疑自己:我应该如何向用户展示从模型获得的结果?电影的制作年份是第一还是最后一年?)

视图:哦,searchResultsListObservable…中有一个新触发器,好,有一个可显示的列表,现在我只需要在列表中显示它即可。得到结果后,我还应该隐藏进度栏。[ MVVM ]

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


这里所有的风味文字下都有一个很好的答案...通过一些格式设置和组件之间的闲聊,这可能是此页面上的最佳选择。
neonblitzer

10

使用MVC将强类型的ViewModel注入视图

  1. 控制器负责更新ViewModel并将其注入到View中。(用于获取请求)
  2. ViewModel是DataContext和视图状态(例如最后选择的项等)的容器。
  3. 该模型包含数据库实体,并且非常接近数据库模式,它执行查询和过滤。(为此我喜欢EF和LINQ)
  4. 该模型还应考虑将存储库和/或结果投影到强类型中(EF具有强大的方法... EF.Database.Select(querystring,parms),用于直接ADO访问以注入查询并返回强类型。这解决了EF是慢速参数,EF不是慢速
  5. ViewModel获取数据并执行业务规则和验证
  6. 回发控制器将校准ViewModel Post方法并等待结果。
  7. 控制器会将新更新的Viewmodel注入到View中。视图使用强类型绑定
  8. 该视图仅呈现数据,并将事件发回到控制器。(请参见下面的示例)
  9. MVC截获入站请求并将其路由到具有强数据类型的适当控制器

在此模型中,因为MSFT的MVC机器向我们隐藏了请求或响应对象,所以不再与请求或响应对象进行HTTP级别的联系。

为了澄清以上第6项(应要求)...

假设这样的ViewModel:

public class myViewModel{
     public string SelectedValue {get;set;}
public void Post(){
    //due to MVC model binding the SelectedValue string above will be set by MVC model binding on post back.
    //this allows you to do something with it.
    DoSomeThingWith(SelectedValue);
    SelectedValue = "Thanks for update!";
 }
}

帖子的控制器方法将如下所示(请参见下文),请注意,MVC绑定机制自动实例化了mvm的实例。因此,您永远不必下拉至查询字符串层!这是MVC根据查询字符串为您实例化ViewModel!

[HTTPPOST]   
public ActionResult MyPostBackMethod (myViewModel mvm){
         if (ModelState.IsValid)
        {
               // Immediately call the only method needed in VM...
               mvm.Post()
        }
      return View(mvm);
}

请注意,为了使上面的操作方法按预期工作,您必须定义一个空CTOR,以初始化帖子中未返回的内容。回发还必须回发那些已更改的名称/值对。如果缺少名称/值对,则MVC绑定引擎会执行正确的操作,根本不起作用!如果发生这种情况,您可能会发现自己说“我正在丢失回发的数据” ...

这种模式的优点是ViewModel可以将所有“杂乱的”工作都连接到模型/业务逻辑,控制器只是各种路由器。它是SOC在起作用。


您能否澄清第6项?我意识到您仅涵盖ASP.Net,但似乎为ViewModel添加了不必要的依赖关系。(例如,了解数据的来源/去向)。一个代码(伪代码?)示例可以很好地阐明这个答案,并显示哪些部分在服务器端,哪些部分在客户端。
Gone Coding 2015年

9

MVVM将视图模型添加到组合中。这很重要,因为它允许您使用WPF的许多绑定方法,而无需将所有特定于UI的部分放入常规模型中。

我可能是错的,但我不确定MVVM是否真的将控制器强加于人。我发现这个概念更符合:http : //martinfowler.com/eaaDev/PresentationModel.html。我认为人们选择将其与MVC结合,而不是将其内置到模式中。


3
严格来说,MVVM是表示模型,尽管MVVM已成为WPF特定模式实现的首选名称。
wekempf

同意 MVC中的Viewmodel是“ IS”视图的状态机。它包含数据上下文并跟踪所有选定的项目信息,并可以使用IValidatableObject接口包含所有验证逻辑。ViewModel在可以使用强类型模型的模型层与DB交互。WPF中的MVVM是MVC的控制器。但是MVC的控制器要干净得多,它是必不可少的路由处理程序。
约翰·彼得斯

9

据我所知,MVVM映射到MVC的MV,这意味着在传统的MVC模式中,V不会直接与M通信。在第二版的MVC中,M和V之间存在直接链接。似乎承担了所有与M和V通信有关的任务,并将其耦合以使其与C脱钩。实际上,仍然存在较大范围的应用程序工作流(或使用场景的实现),而MVVM并未完全解决。这是控制器的角色。通过从控制器中删除这些较低级别的方面,它们将变得更清洁,并使修改应用程序的使用场景和业务逻辑更加容易,也使控制器具有更高的可重用性。


1
恕我直言,我认为,“使控制器的更多可重复使用的”是过于宽泛的陈述和适得其反一般ASP.Net“控制器”(即不业务逻辑层)那些控制器通常包含应用程序中的一些部分应用程序-具体的。需要重用的是视图,模型,视图模型和业务逻辑。我本以为将业务逻辑模块视为服务提供者,而不是控制器,将是一个更好的选择。
Gone Coding 2015年

但是您在谈论的是Asp.net中的“ ViewModel”,而不是MVVM设计模式。两件事。
路易斯

9

令我惊讶的是,这是一个高度投票的答案,而没有提及MVVM 的起源MVVM是Microsoft社区中流行的术语,它起源于Martin Fowler的Presentation Model。因此,要了解模式的动机和与他人的差异,关于模式的原始文章是第一读。


哇...所以MVC和MVVM都来自SmallTalk?他们显然比他们的时间提前了……
MattE '16

实际上,说它起源于Martin Fowler的Presentation Model是不准确的。确定哪个先出现是非常困难的,但是两种模式(允许它们实际上是相同的模式)是分别并在大致相同的时间到达的。
wekempf

6

好吧,通常MVC用于Web开发,而MVVM在WPF / Silverlight开发中最流行。但是,有时Web架构师可能同时使用MVC和MVVM。

例如:您可能使用淘汰表.js,在这种情况下,您的客户端将具有MVVM。MVC的服务器端也可以更改。在复杂的应用程序中,没有人使用纯模型。可以将ViewModel用作MVC的“模型”,并且实际的Model基本上将成为此VM的一部分。这为您提供了额外的抽象层。


“ Web开发”术语“ MVC”仅是关注点分离,而不是Web之前的真实MVC。
Terrence Brannon

4

对于企业以及快速的应用程序开发而言,MVVMC或MVC +似乎都是可行的方法。将UI与业务和交互逻辑分开很不错,但“纯” MVVM模式和大多数可用示例在单个视图上效果最佳。

不确定您的设计,但是我的大多数应用程序都包含页面和几个(可重用)视图,因此ViewModels确实需要进行某种程度的交互。使用页面作为控制器将完全破坏MVVM的目的,因此随着应用程序的成熟,不对底层逻辑使用“ VM-C”方法可能会导致结构挑战。即使在VB-6中,我们大多数人也可能停止将业务逻辑编码到Button事件中,并开始向控制器“中继”命令,对吗?我最近查看了关于该主题的许多新兴框架。显然,我最喜欢的是Magellan(在Codeplex上)方法。编码愉快!

http://en.wikipedia.org/wiki/Model_View_ViewModel#References


4

MVVM中的ViewModel不能代替Controller,因为ViewModel的功能与Controller完全不同。您仍然需要一个Controller,因为没有Controller,您的Model,ViewModel和View将不会做很多事情。在MVVM中,您也有Controller,名字MVVM只是误导。

以我的拙见,MVVMC是正确的名称。

如您所见,ViewModel只是MVC模式的补充。它将转换逻辑(例如,将对象转换为字符串)从Controller移至ViewModel。


4

我为此做了一篇中型文章。

MVVM

  1. 查看➡ViewModel➡模型

    • 该视图引用了ViewModel,反之亦然。
    • ViewModel引用了Model,反之亦然。
    • 视图没有引用模型,反之亦然。
  2. 如果您使用的是控制器,则可以引用ViewsViewModels,尽管并非如SwiftUI所示,总是需要控制器。

  3. 数据绑定:我们为ViewModel属性创建侦听器。
class CustomView: UIView {
  var viewModel = MyViewModel {
    didSet {
      self.color = viewModel.color
    }
  }

  convenience init(viewModel: MyViewModel) {
    self.viewModel = viewModel
  }
}


struct MyViewModel {
   var viewColor: UIColor {
      didSet {
         colorChanged?() // This is where the binding magic happens.
      }
   }

   var colorChanged: ((UIColor) -> Void)?
}


class MyViewController: UIViewController {

   let myViewModel = MyViewModel(viewColor: .green)
   let customView: CustomView!

   override func viewDidLoad() {
      super.viewDidLoad()

      // This is where the binder is assigned.
      myViewModel.colorChanged = { [weak self] color in 
        print("wow the color changed")
      }
      customView = CustomView(viewModel: myViewModel)
      self.view = customView
   }
}

设置差异

  1. 业务逻辑保存在MVC的控制器和MVVM的ViewModel中。
  2. 事件从视图直接传递到MVC中的控制器,而事件从视图传递到ViewModel并传递给MVVM的控制器(如果有)。

共同特征

  1. MVVM和MVC都不允许视图直接将消息发送到模型。
  2. 两者都有模型。
  3. 两者都有意见。

MVVM的优势

  1. 由于ViewModels具有业务逻辑,因此它们是较小的具体对象,因此易于进行单元测试。另一方面,在MVC中,业务逻辑位于ViewController中。您如何相信视图控制器的单元测试是全面安全的,而无需同时测试所有方法和侦听器?您不能完全相信单元测试结果。
  2. 在MVVM中,由于业务逻辑从Controller虹吸到原子ViewModel单元中,因此ViewController的大小缩小了,这使ViewController代码更清晰易读。

MVC的优势

  1. 在控制器内提供业务逻辑可减少分支需求,因此语句更可能在缓存上运行,这比将业务逻辑封装到ViewModels中的性能更高。
  2. 在一个地方提供业务逻辑可以加快不需要测试的简单应用程序的开发过程。我不知道什么时候不需要测试。
  3. 对于新开发人员而言,在ViewController中提供业务逻辑更容易考虑。

1
最好的解释
p32094

2

从实际的角度来看,MVC(模型-视图-控制器)是一种模式。但是,将MVC用作ASP.net MVC时,将其与Entity Framework(EF)和“强大工具”结合使用是一种非常强大的,部分自动化的方法,用于将数据库,表和列带到网页上仅CRUD操作或R(检索或读取)操作。至少当我使用MVVM时,视图模型与依赖于业务对象的模型进行了交互,而这些模型又是“手工制造的”,并且经过大量的努力,人们很幸运地获得了与EF所提供的模型一样好的模型。开箱即用”。从实际编程的角度来看,MVC似乎是一个不错的选择,因为它开箱即用地提供了很多实用程序,但是仍然有可能增加麻烦。


2

作为对许多答复的补充,我想从现代客户端Web或Rich Web Application的角度添加一些其他角度。

实际上,如今,简单的网站和较大的Web应用程序通常使用许多流行的库(例如Bootstrap)构建。Knockout由Steve Sanderson构建,为MVVM模式提供了支持,该模式模仿了模式中最重要的行为之一:通过视图模型进行数据绑定。只需使用少量JavaScript,就可以实现数据和逻辑,然后可以将其添加到具有简单data-bindHTML属性的页面元素中,类似于使用Bootstrap的许多功能。这两个库一起提供了交互式内容。当与路由结合使用时,此方法可以生成一种简单但功能强大的方法来构建Single Page Application

类似地,现代客户端框架(例如Angular)按照惯例遵循MVC模式,但也添加了服务。有趣的是,它被吹捧为Model-View-Whatever(MVW)。(请参阅有关堆栈溢出的文章。)

此外,随着Angular 2等渐进式 Web框架的兴起,我们看到了术语的变化,也许正在看到一种新的架构模式,其中组件由视图或模板组成,并与服务交互-所有这些都可以包含在模块;一系列模块组成了应用程序。


2

我曾经认为MVC和MVVM是相同的。现在,由于存在助焊剂,我可以说出区别:

在MVC中,对于应用程序中的每个视图,您都有一个模型和一个控制器,因此我将其称为视图,视图模型,视图控制器。该模式不会告诉您一个视图如何与另一个视图进行通信。因此,在不同的框架中有不同的实现方式。例如,在某些实现中,控制器之间相互通信,而在其他实现中,存在另一个在它们之间进行中介的组件。甚至存在视图模型相互通信的实现,这是MVC模式的突破,因为视图模型只能由视图控制器访问。

在MVVM中,每个组件都有一个视图模型。该模式没有指定视图到底将如何影响视图模型,因此通常大多数框架仅在视图模型中包括控制器的功能。但是,MVVM确实告诉您,视图模型的数据应来自该模型,即整个模型无法识别或针对特定视图定制。

为了演示差异,让我们采用Flux模式。助焊剂模式告诉应用程序中不同的视图应该如何通信。每个视图都监听商店,并使用调度程序触发操作。调度程序又将所有已执行的操作告知所有商店,商店会自行更新。Flux中的商店对应于MVVM中的(通用)模型。它不是针对任何特定视图定制的。因此,通常当人们使用React和Flux时,每个React组件实际上都实现了MVVM模式。发生操作时,视图模型将调用调度程序,最后根据存储区中的更改(即模型)对其进行更新。您不能说每个组件都实现了MVC,因为在MVC中,只有控制器可以更新视图模型。


2

在Web开发中,mvc是服务器端,而mvvm是客户端(浏览器)。

大多数情况下,JavaScript用于浏览器中的mvvm。有许多用于mvc的服务器端技术。


1

简而言之-在MVC中,Controler知道(控件)视图,而在MVVM中,ViewModel不知道谁在使用它。ViewModel将其可观察的属性和操作公开给可能对使用它感兴趣的任何人。这个事实使测试更加容易,因为ViewModel中没有对UI的引用。


1

模型-视图-控制器(通常称为MVC)是一种软件设计模式,通常用于开发用户界面,该界面将相关的程序逻辑分为三个相互连接的元素。这样做是为了将信息的内部表示形式与信息呈现给用户并由用户接受的方式分开。遵循MVC架构模式将这些主要组件解耦,从而允许代码重用和并行开发。

传统上,此模式用于桌面图形用户界面(GUI),在设计Web应用程序时已变得很流行。流行的编程语言(例如JavaScript,Python,Ruby,PHP,Java和C#)具有MVC框架,这些框架可直接用于Web应用程序开发。

模型

模式的中心组成部分。它是应用程序的动态数据结构,独立于用户界面。它直接管理应用程序的数据,逻辑和规则。

视图

信息的任何表示形式,例如图表,图表或表格。可以使用同一信息的多种视图,例如用于管理的条形图和用于会计的表格视图。

控制者

接受输入并将其转换为模型或视图的命令。

除了将应用程序划分为这些组件之外,模型-视图-控制器设计还定义了它们之间的交互。

该模型负责管理应用程序的数据。它从控制器接收用户输入。

视图表示以特定格式表示的模型。

控制器响应用户输入并在数据模型对象上执行交互。控制器接收输入,可选地对其进行验证,然后将输入传递给模型。 在此处输入图片说明

模型–视图–视图模型(MVVM)是一种软件体系结构模式。

MVVM有助于将图形用户界面的开发(通过标记语言或GUI代码)与业务逻辑或后端逻辑(数据模型)的开发分开。MVVM的视图模型是一个值转换器,这意味着视图模型负责以易于管理和呈现对象的方式公开(转换)来自模型的数据对象。在这方面,视图模型比视图更具模型性,可以处理大多数(如果不是全部)视图显示逻辑。视图模型可以实现中介者模式,围绕视图支持的一组用例来组织对后端逻辑的访问。

MVVM是Martin Fowler的Presentation Model设计模式的一种变体。MVVM以相同的方式抽象视图的状态和行为,但是表示模型以不依赖于特定用户界面平台的方式抽象视图(创建视图模型)。

MVVM由Microsoft架构师Ken Cooper和Ted Peters发明,目的是简化事件驱动的用户界面编程。该模式已合并到Windows Presentation Foundation(WPF)(Microsoft的.NET图形系统)和Silverlight(WPF的Internet应用程序派生)中。微软WPF和Silverlight架构师之一约翰·高斯曼(John Gossman)在2005年的博客中宣布了MVVM。

Model-View-ViewModel也称为Model-view-binder,尤其是在不涉及.NET平台的实现中。ZK(用Java编写的Web应用程序框架)和KnockoutJS(JavaScript库)使用模型-视图-绑定器。 在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.