标准的“模型视图控制器”模式和微软的模型/视图/视图模型模式有区别吗?
25 回答
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 指南是:
- 视图显示某种形状的数据。他们不知道数据来自哪里。
- ViewModel持有某种形状的数据和命令,它们不知道数据或代码来自哪里或如何显示。
- 模型保存实际数据(各种上下文、存储或其他方法)
- 控制器监听并发布事件。控制器提供了控制可以查看哪些数据以及在何处查看数据的逻辑。控制器向 ViewModel 提供命令代码,以便 ViewModel 实际上是可重用的。
我们还注意到,Sculpture 代码生成框架实现了 MVVM 和类似于 Prism 的模式,并且它还广泛使用控制器来分离所有用例逻辑。
不要假设控制器已被视图模型淘汰。
我已经开始了一个关于这个主题的博客,我会在可以的时候添加(仅在主机丢失时存档)。将 MVCVM 与常见的导航系统结合起来存在问题,因为大多数导航系统只使用视图和虚拟机,但我将在以后的文章中讨论。
使用 MVCVM 模型的另一个好处是,在应用程序的整个生命周期中,只有控制器对象需要存在于内存中,并且控制器主要包含代码和很少的状态数据(即很小的内存开销)。与必须保留视图模型的解决方案相比,这使得内存密集型应用程序的内存占用少得多,并且它非常适合某些类型的移动开发(例如,使用 Silverlight/Prism/MEF 的 Windows Mobile)。这当然取决于应用程序的类型,因为您可能仍需要保留偶尔缓存的 VM 以提高响应速度。
注意:这篇文章已被多次编辑,并没有专门针对所提出的狭隘问题,所以我已经更新了第一部分,现在也涵盖了。以下评论中的大部分讨论仅与 ASP.Net 相关,与更广泛的情况无关。这篇文章旨在涵盖 MVVM 在 Silverlight、WPF 和 ASP.Net 中的更广泛使用,并试图阻止人们用 ViewModels 替换控制器。
我认为理解这些首字母缩略词应该意味着什么的最简单方法是暂时忘记它们。相反,想想他们所使用的软件,每一个。它真的归结为早期网络和桌面之间的区别。
随着它们在 2000 年代中期变得越来越复杂,在 1970 年代首次描述的 MVC 软件设计模式开始应用于 Web 应用程序。想想数据库、HTML 页面和介于两者之间的代码。让我们稍微改进一下以达到 MVC:对于»database«,让我们假设数据库加上接口代码。对于»HTML 页面«,我们假设 HTML 模板加上模板处理代码。对于“中间代码”,我们假设代码将用户点击映射到操作,可能会影响数据库,肯定会导致显示另一个视图。就是这样,至少出于比较的目的。
让我们保留这个 Web 东西的一个特性,而不是像今天这样,而是像十年前那样,当时 JavaScript 是一种卑鄙、卑鄙的烦恼,真正的程序员很好地避开了这一点:HTML 页面本质上是愚蠢和被动的. 浏览器是一个瘦客户端,或者如果你愿意的话,一个糟糕的客户端。浏览器没有智能。整页重新加载规则。»view« 每次都会重新生成。
让我们记住,这种网络方式尽管风靡一时,但与桌面相比却是可怕的落后。如果您愿意,桌面应用程序是胖客户端或富客户端。(即使是像 Microsoft Word 这样的程序也可以被认为是某种客户端,一个文档客户端。)它们是充满智慧的客户端,对他们的数据充满了知识。他们是有状态的。他们将正在处理的数据缓存在内存中。没有像整页重新加载这样的废话。
而这种丰富的桌面方式可能就是第二个缩写词 MVVM 的起源。不要被字母和 C 的遗漏所迷惑。控制器仍然存在。他们需要。什么都没有被删除。我们只添加一件事:有状态,缓存在客户端的数据(以及处理该数据的智能)。该数据,本质上是客户端上的缓存,现在被称为 »ViewModel«。它允许丰富的交互性。就是这样。
- MVC = 模型、控制器、视图 = 本质上是单向通信 = 交互性差
- MVVM = 模型、控制器、缓存、视图 = 双向通信 = 丰富的交互性
我们可以看到,借助 Flash、Silverlight 以及——最重要的——JavaScript,网络已经接受了 MVVM。浏览器不能再被合法地称为瘦客户端。看看它们的可编程性。看看他们的内存消耗。查看现代网页上的所有 Javascript 交互性。
就个人而言,我发现这个理论和首字母缩略词业务通过查看它在具体现实中所指的内容更容易理解。抽象概念很有用,尤其是在具体问题上进行演示时,因此理解可能会绕一圈。
MVVM Model-View ViewModel类似于MVC,Model-View Controller
控制器被替换为ViewModel。ViewModel 位于 UI 层之下。ViewModel 公开视图所需的数据和命令对象。您可以将其视为视图从中获取其数据和操作的容器对象。ViewModel 从模型中提取数据。
Russel East写了一篇博客,更详细地讨论了 为什么 MVVM 与 MVC 不同
一方面,MVVM 是 MVC 模式的发展,它使用 XAML 来处理显示。 本文概述了两者的一些方面。
模型/视图/视图模型架构的主要推动力似乎是在数据(“模型”)之上,还有另一层非可视组件(“视图模型”)更紧密地映射数据的概念数据视图(“视图”)的概念。View 绑定的是 ViewModel,而不是 Model 直接绑定。
Microsoft在此处提供了对 Windows 环境中的 MVVM 模式的解释。
这是一个关键部分:
在 Model-View-ViewModel 设计模式中,一个应用程序由三个通用组件组成。
模型:这表示您的应用使用的数据模型。例如,在图片共享应用程序中,该层可能表示设备上可用的图片集以及用于读取和写入图片库的 API。
视图:一个应用程序通常由多个 UI 页面组成。向用户显示的每个页面都是 MVVM 术语中的视图。视图是用于定义和设置用户所见内容的 XAML 代码。模型中的数据显示给用户,ViewModel 的工作是根据应用程序的当前状态向 UI 提供这些数据。例如,在图片共享应用程序中,视图将是向用户显示设备上的相册列表、相册中的图片以及向用户显示特定图片的另一个 UI。
ViewModel:ViewModel 将数据模型或简称模型与应用程序的 UI 或视图联系起来。它包含用于管理来自模型的数据的逻辑,并将数据作为一组属性公开,XAML UI 或视图可以绑定到这些属性。例如,在图片共享应用程序中,ViewModel 会公开一个相册列表,并为每个相册公开一个图片列表。UI 不知道图片的来源和检索方式。它只知道 ViewModel 公开的一组图片并将它们显示给用户。
我认为主要区别之一是在 MVC 中,您的 V 直接读取您的 M,并通过 C 来操作数据,而在 MVVM 中,您的 VM 充当 M 代理,并为您提供可用的功能五。
如果我没有满是垃圾,我很惊讶没有人创建混合,您的 VM 只是一个 M 代理,而 C 提供所有功能。
MVC 是受控环境,MVVM 是反应式环境。
在受控环境中,您应该拥有更少的代码和通用的逻辑源;它应该始终存在于控制器中。然而; 在 Web 世界中,MVC 很容易分为视图创建逻辑和视图动态逻辑。创作存在于服务器上,动态存在于客户端。您可以在 ASP.NET MVC 与 AngularJS 的结合中看到很多,而服务器将创建一个视图并传入一个模型并将其发送到客户端。然后客户端将与视图交互,在这种情况下,AngularJS 会作为本地控制器介入。提交后,模型或新模型将传回服务器控制器并进行处理。(因此循环继续,并且在使用套接字或 AJAX 等时,这种处理有很多其他的翻译,但总体而言,架构是相同的。)
MVVM 是一种反应式环境,这意味着您通常编写将基于某些事件激活的代码(例如触发器)。在 MVVM 蓬勃发展的 XAML 中,这一切都可以通过内置的数据绑定框架轻松完成,但如前所述,这将在任何视图中使用任何编程语言的任何系统上工作。它不是特定于 MS 的。ViewModel 触发(通常是属性更改事件),View 根据您创建的任何触发器对其做出反应。这可能是技术性的,但底线是视图是无状态的并且没有逻辑。它只是根据值更改状态。此外,ViewModel 是无状态的,逻辑很少,而模型是具有本质上零逻辑的状态,因为它们应该只维护状态。我将其描述为应用程序状态(模型)、状态转换器(视图模型),然后是视觉状态/交互(视图)。
在 MVC 桌面或客户端应用程序中,您应该有一个模型,并且该模型应该由控制器使用。基于模型,控制器将修改视图。视图通常与具有接口的控制器绑定,以便控制器可以与各种视图一起工作。在 ASP.NET 中,MVC 的逻辑在服务器上稍微倒退,因为控制器管理模型并将模型传递给选定的视图。然后,视图会根据模型填充数据并具有自己的逻辑(通常是另一个 MVC 集,例如使用 AngularJS 完成的)。人们会争论并将这与应用程序 MVC 混淆,并尝试两者都做,此时维护项目最终将成为一场灾难。使用 MVC 时,始终将逻辑和控制放在一个位置。不要在 View 后面的代码中(或通过 JS 用于 Web 的 View 中)编写 View 逻辑来容纳 Controller 或 Model 数据。让控制器改变视图。应该存在于视图中的唯一逻辑是通过它使用的接口创建和运行所需的一切。这方面的一个例子是提交用户名和密码。无论是桌面还是网页(在客户端),只要 View 触发 Submit 操作,Controller 都应该处理提交过程。如果操作正确,您总是可以轻松地在 MVC Web 或本地应用程序中找到自己的方式。无论是桌面还是网页(在客户端),只要 View 触发 Submit 操作,Controller 都应该处理提交过程。如果操作正确,您总是可以轻松地在 MVC Web 或本地应用程序中找到自己的方式。无论是桌面还是网页(在客户端),只要 View 触发 Submit 操作,Controller 都应该处理提交过程。如果操作正确,您总是可以轻松地在 MVC Web 或本地应用程序中找到自己的方式。
MVVM 是我个人最喜欢的,因为它完全是反应式的。如果模型更改状态,ViewModel 会监听并转换该状态,仅此而已!!!然后 View 会监听 ViewModel 的状态变化,它还会根据 ViewModel 的转换进行更新。有些人称它为纯 MVVM,但实际上只有一个,我不在乎你如何争论它,它始终是纯 MVVM,其中视图绝对不包含任何逻辑。
这是一个小例子:假设您希望在按下按钮时滑入菜单。在 MVC 中,您的界面中将有一个 MenuPressed 操作。当你点击 Menu 按钮时,Controller 会知道,然后根据另一个 Interface 方法(例如 SlideMenuIn)告诉 View 在 Menu 中滑动。往返是什么原因?如果控制器决定您不能或想要做其他事情,这就是原因。Controller 应该负责 View,除非 Controller 这么说,否则 View 什么都不做。然而; 在 MVVM 中,动画中的幻灯片菜单应该是内置的并且是通用的,而不是被告知将其滑入,而是基于某些值。所以它会监听 ViewModel 并且当 ViewModel 说 IsMenuActive = true (或者无论如何)时,动画就会发生。现在,话虽如此,我想真正清楚地说明另一点,请注意。IsMenuActive 可能是 BAD MVVM 或 ViewModel 设计。在设计 ViewModel 时,您永远不应该假设 View 将具有任何功能并且只是传递已转换的模型状态。这样,如果您决定更改视图以删除菜单并仅以另一种方式显示数据/选项,则 ViewModel 不在乎。那么您将如何管理菜单?当数据有意义时,就是这样。因此,一种方法是给 Menu 一个选项列表(可能是内部 ViewModel 的数组)。如果该列表有数据,则菜单知道通过触发器打开,如果没有,则它知道通过触发器隐藏。您只需在 ViewModel 中有或没有菜单的数据。不要决定在 ViewModel 中显示/隐藏该数据。简单地转换模型的状态。这种方式视图是完全反应和通用的,可以在许多不同的情况下使用。
如果您还没有至少稍微熟悉每个架构的架构并且学习它可能会非常混乱,因为您会在网上找到很多糟糕的信息,那么所有这些可能完全没有意义。
所以...要记住这一点,要记住的事情。预先决定如何设计您的应用程序并坚持下去。
如果您使用 MVC,这很棒,那么请确保您的 Controller 是可管理的并且可以完全控制您的 View。如果您有一个大视图,请考虑向具有不同控制器的视图添加控件。只是不要将这些控制器级联到不同的控制器。维护起来非常令人沮丧。花点时间以一种可以作为单独组件工作的方式单独设计事物......并且始终让控制器告诉模型提交或持久存储。MVC 中的理想依赖设置是View ← Controller → Model 或使用 ASP.NET(不要让我开始)Model ← View ↔ Controller → Model (其中 Model 可以是相同的,也可以是完全不同的 Model 从控制器到视图)...当然,此时唯一需要了解 View 中的 Controller 主要是为了端点参考,以了解将模型传回何处。
如果你做 MVVM,我会祝福你善良的灵魂,但请花时间做对!不要使用接口之一。让您的视图根据值决定它的外观。使用模拟数据查看视图。如果您最终拥有一个向您显示菜单的视图(根据示例),即使您当时不想要它,那么很好。您的观点正在按应有的方式工作,并根据应有的价值观做出反应。只需向您的触发器添加更多要求,以确保当 ViewModel 处于特定的已翻译状态或命令 ViewModel 清空此状态时不会发生这种情况。在您的 ViewModel 中不要使用内部逻辑删除它,就好像您正在从那里决定视图是否应该看到它一样。请记住,您不能假设 ViewModel 中有或没有菜单。最后,模型应该只允许您更改并且最有可能存储状态。这就是验证和一切都会发生的地方;例如,如果模型不能修改状态,那么它只会将自己标记为脏或其他东西。当 ViewModel 意识到这一点时,它将翻译什么是脏的,然后 View 将意识到这一点并通过另一个触发器显示一些信息。View 中的所有数据都可以绑定到 ViewModel,因此只有 Model 可以是动态的,而 ViewModel 完全不知道 View 将如何对绑定做出反应。事实上,模型也不知道视图模型。设置依赖项时,他们应该这样指向并且只指向这样 t 修改状态然后它会简单地将自己标记为脏或其他东西。当 ViewModel 意识到这一点时,它将翻译什么是脏的,然后 View 将意识到这一点并通过另一个触发器显示一些信息。View 中的所有数据都可以绑定到 ViewModel,因此只有 Model 可以是动态的,而 ViewModel 完全不知道 View 将如何对绑定做出反应。事实上,模型也不知道视图模型。设置依赖项时,他们应该这样指向并且只指向这样 t 修改状态然后它会简单地将自己标记为脏或其他东西。当 ViewModel 意识到这一点时,它将翻译什么是脏的,然后 View 将意识到这一点并通过另一个触发器显示一些信息。View 中的所有数据都可以绑定到 ViewModel,因此只有 Model 可以是动态的,而 ViewModel 完全不知道 View 将如何对绑定做出反应。事实上,模型也不知道视图模型。设置依赖项时,他们应该这样指向并且只指向这样 View 中的所有数据都可以绑定到 ViewModel,因此只有 Model 可以是动态的,而 ViewModel 完全不知道 View 将如何对绑定做出反应。事实上,模型也不知道视图模型。设置依赖项时,他们应该这样指向并且只指向这样 View 中的所有数据都可以绑定到 ViewModel,因此只有 Model 可以是动态的,而 ViewModel 完全不知道 View 将如何对绑定做出反应。事实上,模型也不知道视图模型。设置依赖项时,他们应该这样指向并且只指向这样View → ViewModel → Model (以及这里的旁注......这也可能会引起争论,但我不在乎......不要将模型传递给视图,除非该模型是不可变的;否则用正确的视图模型。视图不应该看到模型周期。我给老鼠破解你看过的演示或你是如何做到的,这是错误的。)
这是我的最后一个提示... 查看一个设计良好但非常简单的 MVC 应用程序,并为 MVVM 应用程序做同样的事情。一个人将拥有更多的控制权,但灵活性有限,而另一个人将没有控制权和无限的灵活性。
受控环境有利于从一组控制器或(单个源)管理整个应用程序,而反应式环境可以分解为单独的存储库,完全不知道应用程序的其余部分在做什么。微观管理与自由管理。
如果我还没有让您感到困惑,请尝试与我联系...我不介意通过插图和示例详细了解这一点。
归根结底,我们都是程序员,并且在编码时存在着无政府状态......所以规则会被打破,理论会改变,所有这一切最终都会被洗白......但是当在大型工作时在项目和大型团队中,就设计模式达成一致并实施它确实很有帮助。有朝一日,它会使一开始采取的额外小步骤在以后成为突飞猛进的储蓄。
简单的区别:(受 Yaakov 的 Coursera AngularJS 课程启发)
MVC(模型视图控制器)
- 模型:模型包含数据信息。不调用或使用 Controller 和 View。包含业务逻辑和表示数据的方式。这些数据中的一些可能以某种形式显示在视图中。它还可以包含从某个源检索数据的逻辑。
- 控制器:充当视图和模型之间的连接。视图调用控制器,控制器调用模型。它基本上通知模型和/或视图进行适当的更改。
- View:处理 UI 部分。与用户交互。
MVVM(模型视图视图模型)
视图模型:
- 它是视图状态的表示。
- 它保存视图中显示的数据。
- 响应查看事件,也就是表示逻辑。
- 调用其他功能进行业务逻辑处理。
- 永远不要直接要求视图显示任何内容。
对于不太熟悉架构模式主题的人来说,其他答案可能不容易理解。对应用程序架构不熟悉的人可能想知道它的选择如何在实践中影响她的应用程序以及社区中的所有大惊小怪。
为了阐明上述内容,我编写了这个涉及 MVVM、MVP 和 MVC 的剧本。故事从用户点击电影搜索应用程序中的“查找”按钮开始……:
用户:点击……</p>
观点:那是谁?[ MVVM|MVP|MVC ]
用户:我刚刚点击了搜索按钮……</p>
观点:好的,等一下…… [ MVVM|MVP|MVC ]
(视图调用ViewModel | Presenter | Controller ...) [ MVVM|MVP|MVC ]
视图:嘿ViewModel | 主持人| 控制器,一个用户刚刚点击了搜索按钮,我该怎么办?[ MVVM|MVP|MVC ]
视图模型| 主持人| 控制器:嘿视图,那个页面上有搜索词吗?[ MVVM|MVP|MVC ]
观点:是的,……这里是……“钢琴” [ MVVM|MVP|MVC ]
—— 这是MVVM和MVP最重要的区别| MVC ———</p>
主持人| 控制器:谢谢View,... 同时我正在查找模型上的搜索词,请给他/她显示一个进度条 [ MVP | MVC ]
(Presenter | Controller正在调用模型……) [ MVP | MVC ]
ViewModel :谢谢,我会在Model上查找搜索词,但不会直接更新您。相反,如果有任何结果,我将触发事件到 searchResultsListObservable。所以你最好注意这一点。[ MVVM ]
(在观察 searchResultsListObservable 中的任何触发器时,View认为它应该向用户显示一些进度条,因为ViewModel不会与它对话)
——————————————————————————————</p>
视图模型| 主持人| 控制器:嘿模型,你有匹配这个搜索词吗?:“钢琴” [ MVVM | 最有价值球员| MVC ]
型号:嘿ViewModel | 主持人| 控制器,让我检查一下…… [ MVVM | 最有价值球员| MVC ]
(模型正在查询电影数据库……) [ MVVM | 最有价值球员| MVC ]
( 过了一会儿 … )
————这就是MVVM、MVP和MVC的分歧点 ——————</p>
模型:我为你找到了一个列表,ViewModel | Presenter,这里是 JSON “[{“name”:”Piano Teacher”,”year”:2001},{“name”:”Piano”,”year”:1993}]” [ MVVM | 最有价值球员]
模型:有一些可用的结果,控制器。我在我的实例中创建了一个字段变量并用结果填充它。它的名字是“searchResultsList” [ MVC ]
(Presenter | Controller感谢Model并返回View) [ MVP | MVC ]
主持人:感谢您的等待,我为您找到了一个匹配结果列表,并将它们排列成一个像样的格式:[“Piano Teacher 2001”,”Piano 1993”] 。也请现在隐藏进度条[ MVP ]
控制器:感谢您等待View,我已经向 Model 询问了您的搜索查询。它说它找到了一个匹配结果列表并将它们存储在其实例内名为“searchResultsList”的变量中。你可以从那里得到它。也请现在隐藏进度条 [ MVC ]
ViewModel : searchResultsListObservable 上的任何观察者都会被通知有这个新列表的格式:[“Piano Teacher 2001”,”Piano 1993”]。[ MVVM ]
观点:非常感谢Presenter [ MVP ]
View : 谢谢“<em>Controller” [ MVC ] (现在View正在质疑自己:我应该如何将我从模型中得到的结果呈现给用户?电影的制作年份应该排在第一位还是最后...?)
View : 哦,在 searchResultsListObservable 里有一个新的触发器……,很好,有一个像样的列表,现在我只需要在一个列表中显示它。既然我有结果,我也应该隐藏进度条。[ MVVM ]
如果你有兴趣,我在这里写了一系列文章,通过实现一个电影搜索安卓应用程序来比较 MVVM、MVP 和 MVC。
MVVM 是表示模型模式的改进(有争议)。我说有争议,因为唯一的区别在于 WPF 如何提供数据绑定和命令处理的能力。
视图模型是用户界面元素的“抽象”模型。它必须允许您以非可视方式执行视图中的命令和操作(例如测试它)。
如果您使用过 MVC,您可能有时会发现创建模型对象以反映视图的状态很有用,例如,显示和隐藏一些编辑对话框等。在这种情况下,您使用的是视图模型。
MVVM 模式只是将该实践推广到所有 UI 元素。
而且它不是 Microsoft 模式,附加的是 WPF / Silverlight 数据绑定特别适合使用这种模式。但是,例如,没有什么能阻止您将它与 java 服务器端一起使用。
令我惊讶的是,这是一个投票率很高的答案,却没有提及 MVVM 的起源。MVVM是微软社区中使用的一个流行术语,它起源于 Martin Fowler 的Presentation Model。因此,要了解该模式的动机以及与其他模式的不同之处,首先要阅读有关该模式的原始文章。
使用 MVC 将强类型视图模型注入视图
- 控制器负责更新 ViewModel 并将其注入到 View 中。(用于获取请求)
- ViewModel 是 DataContext 和视图状态的容器,例如最后选择的项目等。
- 该模型包含数据库实体,并且非常接近它执行查询和过滤的数据库模式。(为此我喜欢 EF 和 LINQ)
- 模型还应该考虑将存储库和/或结果投影到强类型中(EF 有一个很好的方法...... EF.Database.Select(querystring, parms) 用于直接 ADO 访问以注入查询并取回强类型。这解决了 EF是缓慢的论点。EF 不慢!
- ViewModel 获取数据并执行业务规则和验证
- 回发的控制器将调用 ViewModel Post 方法并等待结果。
- 控制器会将新更新的 Viewmodel 注入到 View 中。视图只使用强类型绑定。
- 视图仅呈现数据,并将事件发送回控制器。(见下面的例子)
- MVC 拦截入站请求并将其路由到具有强数据类型的适当控制器
在这个模型中,不再有与请求或响应对象的 HTTP 级别联系,因为 MSFT 的 MVC 机器对我们隐藏了它。
为澄清上述第 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!";
}
}
帖子的控制器方法将如下所示(见下文),请注意 mvm 的实例是由 MVC 绑定机制自动实例化的。结果,您永远不必下拉到查询字符串层!这是 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 之间存在直接链接。MVVM似乎承担了与 M 和 V 通信相关的所有任务,并将其与 C 解耦。实际上,仍然存在更大范围的应用程序工作流(或使用场景的实现),但在 MVVM 中没有完全考虑。这就是控制器的作用。通过从控制器中移除这些较低级别的方面,它们更干净,并且更容易修改应用程序的使用场景和业务逻辑,也使控制器更具可重用性。
MVVM
- 视图➡视图模型➡模型
- 该视图具有对 ViewModel 的引用,但反之则不然。
- ViewModel 具有对 Model 的引用,但反之则不然。
- 视图没有参考模型,反之亦然。
- 如果您使用的是控制器,它可以引用Views和ViewModels,尽管控制器并不总是必需的,如SwiftUI中所示。
- 数据绑定:我们为 ViewModel 属性创建侦听器,以便数据可以通过视图模型从视图流向模型。虽然引用是一种方式:View ➡ ViewModel ➡ Model,但数据需要流动:View ↔ ViewModel ↔ Model。通过读取它自己的属性,它清楚视图如何从模型中获取数据。数据绑定是如何检测视图中的事件并将它们反馈给模型。
class CustomView: UIView {
var viewModel = MyViewModel {
didSet {
self.color = viewModel.viewColor
}
}
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
}
}
设置差异
- 业务逻辑保存在 MVC 的控制器和 MVVM 的 ViewModel 中。
- 事件直接从视图传递到 MVC 中的控制器,而事件从视图传递到 ViewModel 到 MVVM 的控制器(如果有的话)。
共同特征
- MVVM 和 MVC 都不允许 View 直接向 Model/s 发送消息。
- 两者都有模型。
- 两者都有意见。
MVVM 的优点
- 因为 ViewModel 包含业务逻辑,所以它们是更小的具体对象,使它们易于单元测试。另一方面,在 MVC 中,业务逻辑在 ViewController 中。如果不同时测试所有方法和侦听器,你怎么能相信视图控制器的单元测试是全面安全的?你不能完全相信单元测试的结果。
- 在 MVVM 中,由于业务逻辑从 Controller 中抽取到原子 ViewModel 单元中,因此 ViewController 的大小会缩小,这使得 ViewController 代码更加清晰。
MVC的优点
- 在控制器中提供业务逻辑减少了对分支的需求,因此语句更有可能在缓存上运行,这比将业务逻辑封装到 ViewModel 中性能更高。
- 在一个地方提供业务逻辑可以加速不需要测试的简单应用程序的开发过程。我不知道什么时候不需要测试。
- 在 ViewController 中提供业务逻辑对于新开发人员来说更容易考虑。
嗯,通常 MVC 用于 Web 开发,而 MVVM 在 WPF/Silverlight 开发中最流行。但是,有时 Web 架构可能会混合使用 MVC 和 MVVM。
例如:您可能会使用knockout.js,在这种情况下,您将在客户端拥有 MVVM。而且你的 MVC 的服务器端也可以改变。在复杂的应用程序中,没有人使用纯模型。将 ViewModel 用作 MVC 的“模型”可能有意义,而您的真实模型基本上将成为该 VM 的一部分。这为您提供了一个额外的抽象层。
在 MVVM 中,Controller 不会被 ViewModel 取代,因为 ViewModel 具有与 Controller 完全不同的功能。你仍然需要一个控制器,因为没有控制器你的模型、视图模型和视图将不会做很多事情......在 MVVM 中你也有一个控制器,MVVM 的名称只是误导。
在我看来,MVVMC 是正确的名称。
如您所见,ViewModel 只是 MVC 模式的一个补充。它将转换逻辑(例如将对象转换为字符串)从 Controller 移动到 ViewModel。
简而言之——在 MVC 中,控制器知道(控制)视图,而在 MVVM 中,ViewModel 不知道谁在使用它。ViewModel 将其可观察的属性和操作公开给任何可能对使用它感兴趣的人。这个事实使测试更容易,因为 ViewModel 中没有对 UI 的引用。
MVMC,或者可能是 MVC+,对于企业以及快速应用程序开发来说似乎是一种可行的方法。虽然将 UI 与业务和交互逻辑分开是很好的,但“纯”MVVM 模式和大多数可用示例在单一视图上效果最好。
不确定您的设计,但是我的大多数应用程序都包含页面和几个(可重用)视图,因此 ViewModel 确实需要在某种程度上进行交互。使用页面作为控制器将完全破坏 MVVM 的目的,因此不使用“VM-C”方法来处理底层逻辑可能会导致......好吧......随着应用程序的成熟,具有挑战性的构造。即使在 VB-6 中,我们大多数人也可能停止将业务逻辑编码到 Button 事件中并开始将命令“中继”到控制器,对吧?我最近查看了许多关于该主题的新兴框架;我最喜欢的显然是 Magellan(在 codeplex)方法。快乐编码!
http://en.wikipedia.org/wiki/Model_View_ViewModel#References
从实用的角度来看,MVC(Model-View-Controller)是一种模式。然而,当 MVC 用作 ASP.net MVC 时,当与实体框架 (EF) 和“电动工具”结合使用时,它是一种非常强大的、部分自动化的方法,用于将数据库、表和列引入网页,无论是完整的仅限 CRUD 操作或 R(检索或读取)操作。至少在我使用 MVVM 时,视图模型与依赖于业务对象的模型进行交互,而这些模型又是“手工制作”的,经过大量努力,幸运地得到了与 EF 给出的一样好的模型开箱即用”。从实际编程的角度来看,MVC 似乎是一个不错的选择,因为它提供了许多开箱即用的实用程序,但仍有可能添加一些花里胡哨的东西。
作为给出的许多回复的补充,我想从现代客户端 Web 或富 Web 应用程序的角度添加一些额外的视角。
事实上,如今简单的网站和大型 Web 应用程序通常使用许多流行的库(例如 Bootstrap)构建。Knockout由 Steve Sanderson 构建,提供对 MVVM 模式的支持,该模式模仿了该模式中最重要的行为之一:通过视图模型进行数据绑定。使用一点 JavaScript,可以实现数据和逻辑,然后可以将其添加到具有简单data-bind
HTML 属性的页面元素中,类似于使用Bootstrap的许多功能。这两个库单独一起提供交互式内容。当与路由相结合时,这种方法可以产生一种简单而强大的方法来构建单页应用程序。
类似地,像Angular这样的现代客户端框架按照约定遵循 MVC 模式,但也添加了一个服务。有趣的是,它被吹捧为 Model-View-Whatever (MVW)。(请参阅Stack Overflow 上的这篇文章。)
此外,随着 Angular 2 等渐进式 Web 框架的兴起,我们看到了术语的变化,也许还有一种新的架构模式,其中组件由视图或模板组成并与服务交互——所有这些都可以包含在一个模块; 和一系列模块组成了应用程序。
我曾经认为MVC和MVVM是一样的。现在由于 Flux 的存在,我可以区分:
在 MVC 中,对于应用程序中的每个视图,您都有一个模型和一个控制器,所以我称之为视图、视图模型、视图控制器。该模式没有告诉您一个视图如何与另一个视图进行通信。因此,在不同的框架中,有不同的实现。例如,在某些实现中,控制器相互通信,而在其他实现中,有另一个组件在它们之间进行调解。甚至还有视图模型相互通信的实现,这是对 MVC 模式的突破,因为视图模型只能由视图控制器访问。
在 MVVM 中,每个组件都有一个视图模型。该模式没有指定视图应该如何影响视图模型,因此通常大多数框架只是在视图模型中包含控制器的功能。但是,MVVM 确实告诉您,您的视图模型的数据应该来自模型,这是整个模型不知道或自定义到特定视图。
为了演示差异,让我们以 Flux 模式为例。Flux 模式告诉应用程序中的不同视图应该如何通信。每个视图都监听一个存储并使用调度程序触发操作。调度程序反过来告诉所有商店关于刚刚执行的操作,并且商店会自行更新。Flux 中的存储对应于 MVVM 中的(通用)模型。它不是任何特定视图的习惯。所以通常人们在使用 React 和 Flux 时,每个 React 组件实际上都实现了 MVVM 模式。当一个动作发生时,视图模型调用调度器,最后它根据存储中的变化进行更新,也就是模型。你不能说每个组件都实现了 MVC,因为在 MVC 中只有控制器可以更新视图模型。
mvc 是服务器端,mvvm 是 Web 开发中的客户端(浏览器)。
大多数时候 javascript 用于浏览器中的 mvvm。mvc 有很多服务器端技术。
模型-视图-控制器(通常称为MVC)是一种软件设计模式,通常用于开发用户界面,将相关的程序逻辑划分为三个相互关联的元素。这样做是为了将信息的内部表示与信息呈现给用户和被用户接受的方式分开。遵循 MVC 架构模式将这些主要组件解耦,从而允许代码重用和并行开发。
传统上用于桌面图形用户界面 (GUI),这种模式在设计 Web 应用程序时变得很流行。JavaScript、Python、Ruby、PHP、Java 和 C# 等流行的编程语言具有开箱即用的用于 Web 应用程序开发的 MVC 框架。
模型
模式的中心组件。它是应用程序的动态数据结构,独立于用户界面。它直接管理应用程序的数据、逻辑和规则。
看法
信息的任何表示形式,例如图表、图表或表格。相同信息的多个视图是可能的,例如用于管理的条形图和用于会计师的表格视图。
控制器
接受输入并将其转换为模型或视图的命令。
除了将应用程序划分为这些组件之外,模型-视图-控制器设计还定义了它们之间的交互。
模型负责管理应用程序的数据。它接收来自控制器的用户输入。
视图意味着以特定格式呈现模型。
控制器响应用户输入并在数据模型对象上执行交互。控制器接收输入,可选地对其进行验证,然后将输入传递给模型。
模型-视图-视图模型(MVVM) 是一种软件架构模式。
MVVM 有助于将图形用户界面的开发(无论是通过标记语言还是 GUI 代码)与业务逻辑或后端逻辑(数据模型)的开发分开。MVVM 的视图模型是一个值转换器,这意味着视图模型负责以易于管理和呈现对象的方式从模型中公开(转换)数据对象。在这方面,视图模型比视图更像模型,并且处理大部分(如果不是全部)视图的显示逻辑。视图模型可以实现中介者模式,围绕视图支持的用例集组织对后端逻辑的访问。
MVVM 是 Martin Fowler 的演示模型设计模式的一种变体。MVVM 以相同的方式抽象视图的状态和行为,但 Presentation Model 以不依赖于特定用户界面平台的方式抽象视图(创建视图模型)。
MVVM 由 Microsoft 架构师 Ken Cooper 和 Ted Peters 发明,专门用于简化用户界面的事件驱动编程。该模式被纳入 Windows Presentation Foundation (WPF)(Microsoft 的 .NET 图形系统)和 Silverlight(WPF 的 Internet 应用程序衍生产品)。微软的 WPF 和 Silverlight 架构师之一 John Gossman 于 2005 年在他的博客上宣布了 MVVM。
模型-视图-视图模型也称为模型-视图-绑定器,尤其是在不涉及 .NET 平台的实现中。ZK(一个用 Java 编写的 Web 应用程序框架)和 KnockoutJS(一个 JavaScript 库)使用模型-视图-绑定器。