标准的“模型视图控制器”模式和微软的模型/视图/视图模型模式之间有区别吗?
当前回答
MVVM
视图➡视图模型➡模型
视图有对ViewModel的引用,反之则没有。 ViewModel有对模型的引用,反之则没有。 视图没有对模型的引用,反之亦然。
如果你正在使用一个控制器,它可以有一个视图和视图模型的引用,尽管控制器并不总是必要的,就像在SwiftUI中演示的那样。 数据绑定:我们为ViewModel属性创建侦听器,这样数据就可以通过视图模型从视图流向模型。虽然这些引用是单向的:View↔ViewModel↔Model,但数据需要流动:View↔ViewModel。视图如何通过读取自己的属性从模型中获取数据是很清楚的。数据绑定是如何在视图中检测事件并将它们反馈给模型。
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的ViewModels中。 在MVC中,事件直接从视图传递到控制器,而在MVVM中,事件从视图传递到ViewModel再到控制器(如果有的话)。
共同的特征
MVVM和MVC都不允许视图直接向模型发送消息。 两者都有自己的模型。 两人都有自己的观点。
MVVM的优点
因为viewmodel包含业务逻辑,所以它们是更小的具体对象,便于进行单元测试。另一方面,在MVC中,业务逻辑在ViewController中。如果不同时测试所有的方法和侦听器,你怎么能相信视图控制器的单元测试是全面安全的呢?您不能完全相信单元测试结果。 在MVVM中,由于业务逻辑从控制器中被抽取到原子ViewModel单元中,ViewController的大小缩小了,这使得ViewController代码更加清晰。
MVC的优点
在控制器中提供业务逻辑减少了对分支的需求,因此语句更有可能在缓存上运行,这比将业务逻辑封装到ViewModels中性能更好。 在一个地方提供业务逻辑可以加速不需要测试的简单应用程序的开发过程。我不知道什么时候不需要检查。 对于新开发人员来说,在ViewController中提供业务逻辑更容易考虑。
其他回答
MVVM将视图模型添加到混合中。这很重要,因为它允许您大量使用WPF的绑定方法,而无需将所有特定于UI的部分放在常规模型中。
我可能是错的,但是我不确定MVVM真的强迫控制器混合。我发现这个概念更符合:http://martinfowler.com/eaaDev/PresentationModel.html。我认为人们选择将其与MVC结合起来,而不是将其内置到模式中。
使用MVC将强类型视图模型注入到视图中
控制器负责更新ViewModel并将其注入View中。(用于get请求) ViewModel是DataContext和视图状态(如最后选中的项目等)的容器。 模型包含数据库实体,非常接近数据库模式,它进行查询和过滤。(我喜欢EF和LINQ) 模型还应该考虑存储库和或将结果投影到强类型(EF有一个很好的方法……EF.Database。选择(querystring, parms)直接ADO访问注入查询和返回强类型。这解决了EF是缓慢的参数。EF并不慢! ViewModel获取数据并执行业务规则和验证 post后面的控制器将调用ViewModel post方法并等待结果。 控制器会将最新更新的视图模型注入到视图中。视图只使用强类型绑定。 视图仅仅呈现数据,并将事件发送回控制器。(参见下面的例子) 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);
}
注意,为了让上面的actionmethod像你想要的那样工作,你必须定义一个空CTOR来初始化post中没有返回的东西。回发也必须回发那些发生变化的名称/值对。如果缺少名称/值对,MVC绑定引擎就会做正确的事情,而这根本不是什么!如果发生这种情况,你可能会发现自己说“我正在丢失回post的数据”…
这种模式的优点是ViewModel做了所有“杂乱”的工作,接口到模型/业务逻辑,控制器只是一个路由器。这是SOC在起作用。
首先,MVVM是使用XAML处理显示的MVC模式的发展。本文概述了这两者的一些方面。
模型/视图/视图模型架构的主要目的似乎是在数据(“模型”)之上,还有另一层非可视组件(“视图模型”),它将数据的概念更紧密地映射到数据的视图(“视图”)的概念。视图绑定的是ViewModel,而不是直接绑定模型。
除了给出的许多回答之外,我还想从现代客户端web或富web应用程序的角度添加一些额外的观点。
事实上,现在简单的网站和较大的网络应用程序通常是用许多流行的库(如Bootstrap)构建的。Knockout由Steve Sanderson构建,提供了对MVVM模式的支持,该模式模仿了模式中最重要的行为之一:通过视图模型进行数据绑定。只需一点点JavaScript,就可以实现数据和逻辑,然后使用简单的数据绑定HTML属性将其添加到页面元素中,类似于使用Bootstrap的许多特性。这两个库单独提供互动内容;当与路由结合使用时,这种方法可以产生一种简单而强大的方法来构建单页应用程序。
类似地,现代客户端框架(如Angular)遵循MVC模式,但也添加了一个服务。有趣的是,它被吹捧为模型-视图- whatever (MVW)。(参见Stack Overflow上的这篇文章。)
此外,随着渐进式web框架(如Angular 2)的兴起,我们看到了术语的变化,也许还有一种新的架构模式,组件由视图或模板组成,并与服务交互——所有这些都可以包含在模块中;和一系列模块组成的应用程序。
简而言之,在MVC控制器中,ViewModel知道(控件)视图,而在MVVM中,ViewModel不知道谁使用它。ViewModel将其可观察属性和操作公开给任何可能对使用它感兴趣的人。这一事实使得测试更容易,因为在ViewModel中没有对UI的引用。