WPF MVVM模式中,Model和ViewModel到底有什么区别?该怎么理解ViewModel?

版权声明:本文为博主原创或网络整理文章,转载请标明出处,谢谢。 https://blog.csdn.net/nodeman/article/details/84579104

网络收集整理

一、

Model 是用来与后台通讯的东西,甚至你可以不考虑,或者直接使用一种 mapping 机制来自动更新到 ViewModel上(例如直接将 json 内容更新到 ViewModel、或者相反地直接从 ViewModel 中取得一些字段用于通讯)。

实际上核心在于 V 与 ViewModel 的双向绑定机制上。ViewModel 是基于 View 来设计的,目的是让 View 中许多机制直接声明——而不需要写一行代码!

因此 ViewModel 并不是从简单数据通讯角度来设计的,而是从丰富的界面需求来设计的。

很显然,编程很长时间但是比较“懒”得去研究前端“界面”设计的人可能会强调 Model 而懒得去研究 ViewModel,而注重美工效果的程序员会注重 ViewModel。

Model甚至可以忽略,因为它只是干巴巴地“save到后台、search后台”之类的数据操作,其实没有什么东西。

二、

比如你对这个 csdn 帖子页面建立 ViewModel,你照着界面美工设计来开发 ViewModel,这一个 VM上有顶部标题、广告、用户登录信息、私信提醒信息、左边广告、右边广告、中间帖子的标题、中间帖子内容、每一楼层回帖、底部功能菜单、底部广告、当前页号、总页数......等信息,并且 VM 上有“刷新、结贴、回复”等等功能函数,可能还有“动态模板名称、动态样式表名称、页面的风格(浅色的还是深色的).......等许多属性。

你设计 VM 时,是基于数据与 html 双向绑定来设计的,而跟 Model 毫无关系!你的 VM 是丰富的页面表示信息,是从 html 中抽离出来的数据部分和功能部分。因为有了 VM,那么你的 html 就能直接用声明方式来写,而不需要写一行代码。例如当你的页面从浅色系改为深色系时,只要修改 VM 对象的一个属性,它就自动更新 html 上的许多部分,这是因为 html 上许多部分(样式、布局、内容等等)都跟这个属性绑定的,会自动切换。

而 VM 中个别的 save、search 方法,需要从后台交换数据,这时候才需要 Model 实体。比如说你使用 jQuery.get 方式下载页面“回帖”列表,那么回调而得到的 json 对象对应了后台系统查询到的一个页面的回帖数组;如果你使用 jQuery.get 方式下载页面上某个作者的 Avatar 信息,那么回调而得到的 json对象对应了后台系统查询到的这个作者的头像、昵称、级别等信息。这种前后台数据交换的格式,叫做 model。


真正好的程序设计师,满脑子都是从前端美工、交互需求出发的设计。而一些比较垃圾的程序员,即使工作了10年,他满脑子也只有“增删改查”,跟一个刚刚工作1年的程序员没有太大分别。

VM 是极端丰富的交互设计内容,只不过是从 html、xaml 等模板中剥离出来的程序代码部分,所以才用 VM 来支撑 V。而 M 是干巴巴的,就是简单的数据实体。


三、

传统的编程,可能是 V-M 的,也就是混乱的代码跟模板放在一起,然后组件化开发。

而 M-V-VM 模式主张将 V 和 VM 剥离开来,主张 V 尽量只声明、不写代码,解放了偏向美工的程序人员的生产效率,让程序自动化更新的逻辑更清晰、程序更简洁。


四、

假设一个应用中 Model 有50个,代码1000行,ViewModel 有20个,代码15000行,你可以看到的是,Model 作为实体类就跟数据库表的字段结构一样是“失血的”,非常简单。而ViewModel 集中了前端几乎所有的编程内容(不需要编程而用binding 机制来声明的,放到 View 模板上了)。

ViewModel 的设计来自于丰富的交互界面,前端设计千变万化所以随时增加。Model 来自与前后台数据交互,显然它收到后台业务层和数据层的限制而变化不大。

所花的精力上,优秀的前端设计总是反复设计修改,最终会把99%以上的精力投入View+ViewModel。而 Model 相关部分,几乎就是把服务器系统的接口 copy 过来、翻一下数据格式从而能前后台通讯,就没有开发工作量了!


五、

比如说你的某一个 ViewModel 中有一个 ObservableCollection<急救车定位信息> 类型的集合,你的 View 上面于是就有一个 Repeater 控件用来绑定了这个集合,根据每一个定位信息在地图上分别显示不同的急救车图像、方位、颜色、编辑模板名称、显示模板名称、位置、其它标注信息!

此时,这个集合是 ViewModel,并且“急救车定位信息”通常也是 ViewModel。因为地图上的图像、坐标、标注等等,都要跟“急救车定位信息”双线绑定,当用户拖动地图上的急救车的时候、编辑地图上的急救车的信息时,数据要自动更新到这个集合中,以及这个集合的相应的定位信息对象中。

当用户在地图上点击“保存”按钮时,你的这个 ViewModel 的一个 Save 函数被触发,在这个函数中它需要将数据 mapping 转换为

Model.急救车信息[ ]
数组,或者List<Model.急救车信息> 集合,然后调用网关接口程序,把数据送给服务器。

这里要注意的是,ViewModel 中的急救车定位信息集合、以及急救车定位信息,都是基于ViewModel来设计的。而后台通讯用的急救车信息集合、以及急救车信息,是基于 Model 来设计的。简单来说,ViewModel 需要对 Model 注入大量交互行为,以及大量冗余的计算功能,才能支持与 View的双向绑定。所以通常不可能直接把 Model 作为 ViewModel 的一部分,而是需要 mapping,需要为 model 的没一个字段注入新鲜的面向前端的“血液”代码,需要增加数倍的冗余的字段,才能将 model 变为 ViewModel 使用。

所以如果说哪一个重要、哪一个不重要,实际上 model 可以忽视不见,只要知道与后台服务器通讯需要什么结构就好了。ViewModel 才是设计重点,了解它才能对前端设计“落地”。


六、提炼

1、Model简单地说就是一个对象,例如表示一个Student,一个School,甚至可以说是数据表的映射
2、View表示一个窗口,代码只负责显示各种控件,不负责业务逻辑
3、ViewModel是View逻辑的实现,View里面的逻辑都在此实现,比如在ViewModel里面增删查改View中要显示的Student集合,会自动在View中实现,另外在此也可以控制View中控件的状态,例如显示隐藏、进度条等

总结,Model反映实体的数据结构,ViewModel反映界面的状态和逻辑,他们是两个不同的概念

猜你喜欢

转载自blog.csdn.net/nodeman/article/details/84579104