标准“模型视图控制器”模式和Microsoft的Model / View / ViewModel模式之间有区别吗?
标准“模型视图控制器”模式和Microsoft的Model / View / ViewModel模式之间有区别吗?
Answers:
在ASP.Net和Silverlight / WPF开发中,这两种模式以不同的方式出现。
对于ASP.Net,MVVM用于在视图内双向绑定数据。这通常是客户端实现(例如,使用Knockout.js)。另一方面,MVC是一种在服务器端分离问题的方法。
对于Silverlight和WPF,MVVM模式更具涵盖性,并且似乎可以替代MVC(或将软件组织成单独职责的其他模式)。一个假设,经常来到这个模式中出来,是,ViewModel
简单地更换控制器MVC
(如如果你可以只替换VM
为C
的缩写,所有会原谅)...
问题是:要独立测试*,尤其是在需要时可重用,则视图模型不知道显示哪个视图,更重要的是不知道其数据来自何处。
*注意:实际上,控制器从ViewModel中删除了需要进行单元测试的大多数逻辑。然后,VM成为一个哑容器,几乎不需要测试。这是一件好事,因为VM只是设计人员和编码人员之间的桥梁,因此应保持简单。
即使在MVVM中,控制器通常也将包含所有处理逻辑,并决定使用哪种视图模型在哪些视图中显示哪些数据。
到目前为止,我们已经看到ViewModel模式的主要好处是可以从XAML代码背后删除代码,从而使XAML编辑成为更加独立的任务。我们仍然会根据需要创建控制器,以控制(无双关语)应用程序的整体逻辑。
我们还注意到,Sculpture代码生成框架实现了MVVM和类似于Prism的模式,并且还广泛使用了控制器来分隔所有用例逻辑。
我已经开始撰写有关此主题的博客,并将在可能的时候添加到该博客中。将MVCVM与常见的导航系统结合存在问题,因为大多数导航系统仅使用Views和VM,但是我将在以后的文章中进行介绍。
使用MVCVM模型的另一个好处是,在应用程序的生命周期内,仅控制器对象需要存在于内存中,并且控制器主要包含代码和少量状态数据(即,很小的内存开销)。与必须保留视图模型的解决方案相比,这使应用程序占用的内存少得多,并且它对于某些类型的移动开发(例如,使用Silverlight / Prism / MEF的Windows Mobile)非常理想。当然,这确实取决于应用程序的类型,因为您可能仍需要保留偶尔缓存的VM以提高响应能力。
注意:这篇文章已经过多次编辑,并且没有专门针对所提出的狭窄问题,因此我也更新了第一部分,现在也涵盖了这一部分。在下面的评论中,许多讨论仅涉及ASP.Net,而不涉及更广泛的情况。这篇文章旨在涵盖MVVM在Silverlight,WPF和ASP.Net中的更广泛使用,并试图劝阻人们不要使用ViewModels替换控制器。
我认为理解这些首字母缩略词含义的最简单方法是暂时忘记它们。取而代之的是,考虑一下它们起源的软件。实际上,可以归结为早期Web和桌面之间的区别。
随着它们在2000年代中期的复杂性增长,MVC软件设计模式-1970年代首次被描述-开始应用于Web应用程序。考虑数据库,HTML页面和它们之间的代码。让我们对其进行细化以得出MVC:对于»database«,我们假设数据库加上接口代码。对于“ HTML页面”,我们假设HTML模板加上模板处理代码。对于“之间的代码”,我们假设代码将用户的点击映射到操作,这可能会影响数据库,从而肯定会显示另一个视图。就是这样,至少出于此比较的目的。
让我们保留该Web东西的一个功能,而不是今天,而是十年前存在的那年,当时JavaScript是一种卑鄙的,令人卑鄙的烦恼,真正的程序员对此很好地避免了:HTML页面本质上是愚蠢而被动的。浏览器是瘦客户端,或者如果可以的话,它是不良客户端。浏览器中没有智能。整页重新加载规则。每次都会重新生成»view«。
让我们记住,尽管风靡一时,但与台式机相比,这种Web方式仍然落后很多。桌面应用程序可以是胖客户端,也可以是富客户端。(甚至可以将Microsoft Word之类的程序视为某种类型的客户端,即文档的客户端。)它们是充满智能,对数据知识丰富的客户端。他们是有状态的。他们将正在处理的数据缓存在内存中。没有像整页重新加载这样的废话。
这种丰富的桌面方式可能就是第二个缩写MVVM的起源。不要被字母所迷惑,不要被C所迷惑。控制器仍然在那里。他们必须是。什么都不会去除。我们只添加一件事:状态性,缓存在客户端上的数据(以及用于处理该数据的智能)。该数据实际上是客户端上的缓存,现在称为»ViewModel«。这就是允许丰富交互性的原因。就是这样。
我们可以看到,借助Flash,Silverlight和最重要的JavaScript,Web已包含了MVVM。浏览器不再可以合法地称为瘦客户端。看他们的可编程性。看他们的内存消耗。查看现代网页上的所有Javascript交互性。
我个人认为,通过查看具体现实中所指的内容,该理论和首字母缩写词业务更容易理解。抽象的概念很有用,尤其是在具体问题上进行演示时,这样的理解可能会绕一圈。
MVVM Model-View ViewModel与MVC,Model-View Controller类似
控制器被替换为ViewModel。ViewModel位于UI层下面。ViewModel公开了视图所需的数据和命令对象。您可以将其视为视图从其获取数据和操作的容器对象。ViewModel从模型中提取其数据。
Russel East在博客上详细讨论了 为什么MVVM与MVC不同
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. …
一方面,MVVM是MVC模式的演进,该模式使用XAML来处理显示。 本文概述了两者的某些方面。
Model / View / ViewModel体系结构的主要目的似乎是在数据之上(“模型”),还有另一层非可视组件(“ ViewModel”),它们更紧密地映射了数据的概念数据视图(“视图”)的概念。视图绑定到的是ViewModel,而不是直接绑定到Model。
Microsoft 在此处提供了Windows环境中MVVM模式的说明。
这是关键部分:
在Model-View-ViewModel设计模式中,一个应用程序由三个常规组件组成。
模型:这表示您的应用程序使用的数据模型。例如,在图片共享应用中,该层可能表示设备上可用的图片集以及用于读取和写入图片库的API。
视图:一个应用程序通常由多个页面的UI组成。向用户显示的每个页面都是MVVM术语中的一个视图。该视图是用于定义和设置用户所见内容的XAML代码。来自模型的数据会显示给用户,这是ViewModel的工作,它根据应用程序的当前状态向UI提供此数据。例如,在图片共享应用中,视图将是向用户显示设备上的相册列表,相册中的图片以及可能向用户显示特定图片的另一个UI的UI。
ViewModel:ViewModel将数据模型(或简称模型)与应用程序的UI或视图相关联。它包含用于管理模型中数据的逻辑,并将数据公开为XAML UI或视图可以绑定到的一组属性。例如,在图片共享应用中,ViewModel将公开一个相册列表,而对于每个相册,则公开一个图片列表。UI不知道图片来自何处以及如何检索图片。它只是知道ViewModel公开的一组图片并将其显示给用户。
我认为主要区别之一是在MVC中,您的V直接读取您的M,然后通过C来操作数据,而在MVVM中,您的VM充当M代理,并为您提供可用功能V.
如果我还没装满垃圾,我会惊讶的是没有人创建一个混合服务器,其中您的VM只是一个M代理,而C提供了所有功能。
简单差异:(受Yaakov的Coursera AngularJS课程启发)
MVC(模型视图控制器)
MVVM(模型视图视图模型)
ViewModel:
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应用程序执行相同的操作。一个将具有更大的控制权,而灵活性则限于零,而另一个将没有控制权和无限的灵活性。
受控环境非常适合从一组控制器或(单个来源)管理整个应用程序,而反应性环境却可以分解为单独的存储库,而完全不知道应用程序的其余部分在做什么。微管理与免费管理。
如果我对您还没有足够的困惑,请尝试与我联系。。。我不介意通过插图和示例详细介绍这一点。
归根结底,我们都是程序员,编码时无政府状态仍然存在。所以规则将被破坏,理论将发生变化,所有这些最终都会被猪吞噬...但是当从事大型工作时项目和大型团队,这确实有助于达成设计模式并加以实施。有一天,它将使一开始采取的额外小步骤成为节省开支的突飞猛进。
MVVM是Presentation Model模式的改进(值得商de)。我说有争议,因为唯一的区别是WPF如何提供执行数据绑定和命令处理的能力。
对于不太熟悉建筑模式主题的人,其他答案可能不容易理解。应用架构的新手可能想知道它的选择如何在实践中影响她的应用,以及社区中所有的大惊小怪。
为了阐明上述内容,我制作了涉及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 ]
-这是MVVM和MVP之间最重要的区别| 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 ]
( 过了一会儿 … )
----这是之间的分歧点MVVM,MVP和MVC -----
型号:我为您找到了一个列表,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。
在此模型中,因为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在起作用。
MVVM将视图模型添加到组合中。这很重要,因为它允许您使用WPF的许多绑定方法,而无需将所有特定于UI的部分放入常规模型中。
我可能是错的,但我不确定MVVM是否真的将控制器强加于人。我发现这个概念更符合:http : //martinfowler.com/eaaDev/PresentationModel.html。我认为人们选择将其与MVC结合,而不是将其内置到模式中。
据我所知,MVVM映射到MVC的MV,这意味着在传统的MVC模式中,V不会直接与M通信。在第二版的MVC中,M和V之间存在直接链接。似乎承担了所有与M和V通信有关的任务,并将其耦合以使其与C脱钩。实际上,仍然存在较大范围的应用程序工作流(或使用场景的实现),而MVVM并未完全解决。这是控制器的角色。通过从控制器中删除这些较低级别的方面,它们将变得更清洁,并使修改应用程序的使用场景和业务逻辑更加容易,也使控制器具有更高的可重用性。
令我惊讶的是,这是一个高度投票的答案,而没有提及MVVM 的起源。MVVM是Microsoft社区中流行的术语,它起源于Martin Fowler的Presentation Model。因此,要了解模式的动机和与他人的差异,关于模式的原始文章是第一读。
好吧,通常MVC用于Web开发,而MVVM在WPF / Silverlight开发中最流行。但是,有时Web架构师可能同时使用MVC和MVVM。
例如:您可能使用淘汰表.js,在这种情况下,您的客户端将具有MVVM。MVC的服务器端也可以更改。在复杂的应用程序中,没有人使用纯模型。可以将ViewModel用作MVC的“模型”,并且实际的Model基本上将成为此VM的一部分。这为您提供了额外的抽象层。
对于企业以及快速的应用程序开发而言,MVVMC或MVC +似乎都是可行的方法。将UI与业务和交互逻辑分开很不错,但“纯” MVVM模式和大多数可用示例在单个视图上效果最佳。
不确定您的设计,但是我的大多数应用程序都包含页面和几个(可重用)视图,因此ViewModels确实需要进行某种程度的交互。使用页面作为控制器将完全破坏MVVM的目的,因此随着应用程序的成熟,不对底层逻辑使用“ VM-C”方法可能会导致结构挑战。即使在VB-6中,我们大多数人也可能停止将业务逻辑编码到Button事件中,并开始向控制器“中继”命令,对吗?我最近查看了关于该主题的许多新兴框架。显然,我最喜欢的是Magellan(在Codeplex上)方法。编码愉快!
http://en.wikipedia.org/wiki/Model_View_ViewModel#References
MVVM
查看➡ViewModel➡模型
如果您使用的是控制器,则可以引用Views和ViewModels,尽管并非如SwiftUI所示,总是需要控制器。
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
}
}
设置差异
共同特征
MVVM的优势
MVC的优势
作为对许多答复的补充,我想从现代客户端Web或Rich Web Application的角度添加一些其他角度。
实际上,如今,简单的网站和较大的Web应用程序通常使用许多流行的库(例如Bootstrap)构建。Knockout由Steve Sanderson构建,为MVVM模式提供了支持,该模式模仿了模式中最重要的行为之一:通过视图模型进行数据绑定。只需使用少量JavaScript,就可以实现数据和逻辑,然后可以将其添加到具有简单data-bind
HTML属性的页面元素中,类似于使用Bootstrap的许多功能。这两个库一起提供了交互式内容。当与路由结合使用时,此方法可以生成一种简单但功能强大的方法来构建Single Page Application。
类似地,现代客户端框架(例如Angular)按照惯例遵循MVC模式,但也添加了服务。有趣的是,它被吹捧为Model-View-Whatever(MVW)。(请参阅有关堆栈溢出的文章。)
此外,随着Angular 2等渐进式 Web框架的兴起,我们看到了术语的变化,也许正在看到一种新的架构模式,其中组件由视图或模板组成,并与服务交互-所有这些都可以包含在模块;一系列模块组成了应用程序。
我曾经认为MVC和MVVM是相同的。现在,由于存在助焊剂,我可以说出区别:
在MVC中,对于应用程序中的每个视图,您都有一个模型和一个控制器,因此我将其称为视图,视图模型,视图控制器。该模式不会告诉您一个视图如何与另一个视图进行通信。因此,在不同的框架中有不同的实现方式。例如,在某些实现中,控制器之间相互通信,而在其他实现中,存在另一个在它们之间进行中介的组件。甚至存在视图模型相互通信的实现,这是MVC模式的突破,因为视图模型只能由视图控制器访问。
在MVVM中,每个组件都有一个视图模型。该模式没有指定视图到底将如何影响视图模型,因此通常大多数框架仅在视图模型中包括控制器的功能。但是,MVVM确实告诉您,视图模型的数据应来自该模型,即整个模型无法识别或针对特定视图定制。
为了演示差异,让我们采用Flux模式。助焊剂模式告诉应用程序中不同的视图应该如何通信。每个视图都监听商店,并使用调度程序触发操作。调度程序又将所有已执行的操作告知所有商店,商店会自行更新。Flux中的商店对应于MVVM中的(通用)模型。它不是针对任何特定视图定制的。因此,通常当人们使用React和Flux时,每个React组件实际上都实现了MVVM模式。发生操作时,视图模型将调用调度程序,最后根据存储区中的更改(即模型)对其进行更新。您不能说每个组件都实现了MVC,因为在MVC中,只有控制器可以更新视图模型。
模型-视图-控制器(通常称为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库)使用模型-视图-绑定器。