标准的“模型视图控制器”模式和微软的模型/视图/视图模型模式之间有区别吗?


当前回答

微软在这里提供了Windows环境中MVVM模式的解释。

这里有一个关键的部分:

在模型-视图-视图模型设计模式中,应用程序由以下部分组成 三个一般组成部分。 模型:这表示应用程序使用的数据模型。例如,在图片共享应用程序中,此层可能表示 设备上可用的图片集和用于读取和的API 写入图片库。 视图:应用通常由多个UI页面组成。显示给用户的每个页面都是MVVM术语中的一个视图。观点是 用于定义和设置用户所看到内容样式的XAML代码。的数据 从模型显示到用户,这是工作的 的当前状态为UI提供此数据 例如,在一个图片共享应用中,视图就是UI 向用户显示设备上的相册列表,其中的图片 一个相册,或者另一个向用户显示特定信息的相册 图片。 ViewModel: ViewModel将数据模型或简单的模型绑定到应用程序的UI或视图上 哪一个来管理模型中的数据并将数据作为一个集合公开 XAML UI或视图可以绑定到的属性。例如, 在图片共享应用中,ViewModel会显示一个相册列表, 并且为每个相册公开一个图片列表。UI是不可知论的 图片从何而来,如何获取。它只是 知道ViewModel所显示的一组图片,并显示它们 对用户。

其他回答

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中提供业务逻辑更容易考虑。

在web开发中,MVC是服务器端,MVVM是客户端(浏览器)。

大多数情况下,浏览器中的MVVM使用javascript。mvc有很多服务器端技术。

除了给出的许多回答之外,我还想从现代客户端web或富web应用程序的角度添加一些额外的观点。

事实上,现在简单的网站和较大的网络应用程序通常是用许多流行的库(如Bootstrap)构建的。Knockout由Steve Sanderson构建,提供了对MVVM模式的支持,该模式模仿了模式中最重要的行为之一:通过视图模型进行数据绑定。只需一点点JavaScript,就可以实现数据和逻辑,然后使用简单的数据绑定HTML属性将其添加到页面元素中,类似于使用Bootstrap的许多特性。这两个库单独提供互动内容;当与路由结合使用时,这种方法可以产生一种简单而强大的方法来构建单页应用程序。

类似地,现代客户端框架(如Angular)遵循MVC模式,但也添加了一个服务。有趣的是,它被吹捧为模型-视图- whatever (MVW)。(参见Stack Overflow上的这篇文章。)

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

一般来说,MVC用于Web开发,MVVM在WPF/Silverlight开发中最受欢迎。 然而,有时web架构可能混合使用MVC和MVVM。

例如:你可能会使用knockout.js,在这种情况下,你的客户端上会有MVVM。 你的MVC的服务器端也可以改变。在复杂的应用程序中,没有人使用纯模型。使用ViewModel作为MVC的“模型”可能有一定的意义,而你真正的模型基本上将是这个VM的一部分。这为您提供了一个额外的抽象层。

我认为要理解这些首字母缩略词的意思,最简单的方法就是暂时忘掉它们。相反,想想它们源自的软件,每一个软件。这实际上可以归结为早期网络和桌面之间的区别。

在2000年代中期,随着复杂性的增长,MVC软件设计模式(在20世纪70年代首次被描述)开始应用于web应用程序。想想数据库、HTML页面和中间的代码。让我们稍微改进一下以达到MVC:对于»database«,让我们假设数据库加接口代码。对于»HTML页面«,让我们假设HTML模板加上模板处理代码。对于»code inbetween«,让我们假设代码将用户单击映射到操作,可能会影响数据库,肯定会显示另一个视图。就是这样,至少为了比较的目的是这样的。

让我们保留这个网页的一个特性,不是像今天那样,而是像十年前那样,当时JavaScript还是一个低级的、卑鄙的烦恼,真正的程序员很好地避开了:HTML页面本质上是愚蠢和被动的。浏览器是一个瘦客户机,或者可以说是一个穷客户机。浏览器中没有智能。整页重载规则。每次都会重新生成»view«。

让我们记住,尽管这种网络方式风靡一时,但与桌面相比,它是非常落后的。桌面应用程序是胖客户端,也可以说是富客户端。(甚至像Microsoft Word这样的程序也可以被视为某种客户端,文档客户端。)他们是充满智慧的客户,对自己的数据了如指掌。他们是有状态的。它们在内存中缓存正在处理的数据。没有整页重载这种废话。

这种富桌面方式可能就是第二个首字母缩写MVVM的起源。不要被字母所迷惑,也不要被c的省略所迷惑。他们必须如此。没有东西被移除。我们只增加了一件事:状态性,缓存在客户端上的数据(以及处理这些数据的智能)。该数据(本质上是客户机上的缓存)现在被称为»ViewModel«。它允许丰富的交互性。就是这样。

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

我们可以看到,通过Flash、Silverlight,以及最重要的JavaScript, web已经拥抱了MVVM。浏览器不能再被合法地称为瘦客户机。看看它们的可编程性。看看他们的内存消耗。看看现代网页上所有的Javascript交互。

就我个人而言,我发现这个理论和缩略语业务更容易理解,看看它在具体现实中指的是什么。抽象的概念是有用的,特别是在具体的问题上,所以理解可能会有一个完整的循环。