架构模式之MVVM
前言
MVVM是一种架构模式,本文会涉及一小点vue代码,以及一篇简单的springboot的代码,建议在阅读本文档前先对这两门技术做一些学习。
什么是MVVM
MVVM是三个单词的简称,分别是Model,View和ViewModel。
在阐述MVVM的概念之前,让我们先看下这么多年js的发展阶段。
第一阶段,使用原生的js直接操作DOM节点。
var dom = document.getElementById('name');
dom.innerHTML = 'HelloWorld!';
第二阶段,原生API并不是那么的易用,还要考虑浏览器的兼容性,于是Jquery出现了。
$('#name').text('Homer').css('color', 'red');
第三阶段,MVC模式
这个时候就需要服务端应用来配合开发了,用js来根据服务器发送过来的数据进行渲染。
现在,前端页面越来越复杂,用户的交互性操作也越来越多,要求也越来越高,仅仅是使用Jquery已经满足不了前端的需求了,于是MVVM模型出现了。
MVVM借鉴了MVC的思想,在前端页面中,View用于专门的显示,而里面的数据用Model来进行渲染,这样两者就做到了很大程度的分离。
而ViewModel就是用于把Model和View关联起来,Model的数据同步到View显示出来,把View的修改同步回Model,做到这两件事的就是ViewModel。
而这种操作也被称为“双向绑定”。
虽然我们也可以用jquery甚至用原生js来实现MVVM,但Vue自己已经包含了这个功能以及主打的就是它(双向绑定)。
因此Vue基本是MVVM的代言者(个人看法)。
而MVVM的特点也展现出来了。
MVVM的特点
1. 低耦合性。
View可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model不可以不变,当Model变化的时候View也可以不变。
2. 可重用性。
把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑,也就是组件化思想。
3. 独立开发。
开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
MVVM的组成
组成已经在刚刚的对MVVM的介绍中已经说明的很明白了,转换成更直观一些的图就是上面这张。
Model的数据利用ViewModel同步到View显示出来,把View的修改利用ViewModel同步回Model。
View
界面和显示,通常由HTML组成,可以使用各种UI框架组成页面,例如element,不直接与Model交互。
ViewModel
包括界面逻辑和模型数据封装 ,事件响应,绑定的属性等,是View和Model的桥梁
Model
数据核心,连接着ViewModel。
MVVM与MVC
MVC和MVVM的区别其实已经讨论过了,MVVM就是借鉴的MVC的思想,MVC的概念可以去参考另一篇文档。
MVC出现的时候前端还并不是很成熟,很多业务逻辑在后台实现即可,因此当时前端甚至还没有MVC这个概念,MVC的目的就是将Modle和Controller分离,也就是单向通信,而MVVM则是将逻辑重点在前端实现,利用ViewModel进行双向绑定。
MVVM的实现
首先创建一个Helloworld级的html页面,在这里我们使用Vue来感受下MVVM。
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
HelloWorld!
</div>
</body>
<script>
</script>
</html>
创建一个Vue对象
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
HelloWorld!
</div>
</body>
<script>
var app = new Vue({
})
</script>
</html>
这时我们想要使用MVVM思想进行开发,那么就要分别创建出View和Model。
<body>
<div id="app">
{{message}}
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello World!'
}
})
</script>
在这篇短小的代码中,{{message}}代表的就是View,而它则是利用了ViewModel绑定上了在Vue对象中的message变量也就是Model,这就是通过Vue来进行MVVM开发,我们尝试提供给用户一个通道能直接改变Model,看看View会发生生么。
<body>
<div id="app">
{{message}}</br>
<button @click="add">+1个感叹号吧</button>
</div>
</body>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello World!'
},
methods : {
add : function(){
this.message = this.message+"!"
}
}
})
</script>
测试下点击这个按钮会发生什么,
感叹号变成了两个!
让我们根据前面的理论知识来思考下发生了什么,按钮绑定的是methods里面的add方法,在add方法中,我们使代表着Model的变量message的末尾加入了一个感叹号。
Model的变化令ViewModel更新了与Model绑定的View,而此时与Model绑定的View就是{{message}}。
应用场景
首先,我们是不考虑后端模板的,后端模板不利于前后端分离,这是不可争的公认事实,这就不在此处进行讨论说明了。
但如果一些需求需要由前端异步完成,并且是用户修改UI的情况下,我们就需要先保存一份现阶段UI,然后去后台请求完成之后在展示上需要与后端同步,甚至需要用jquery来直接操作dom。
那么MVVM双向绑定呢,我们只需要修改数据Model,因为Model和View是已经绑定好的,因此我们不用在意View怎么样,因为我们在Model改变的时候View就已经改变了。
它的优点
1.双向绑定技术,这是MVVM思想主打的思想,也是它的最优点
2.View可以将后端控制器大量处理的业务放在自己这里,虽然view干了不属于它职责范围内的事,但却将后端控制器大量瘦身了。
3.可以对View的数据处理部分抽象出来一个函数处理model,组成一个功能组件,多次使用。
也总会有不足之处
MVVM确实解决了现阶段前端开发的很多问题,但再厉害的技术,也总会有些许不足。
1.数据绑定使得 Bug 很难被调试。界面出现了异常,有可能是View的代码有问题,也可能是Model。
2.Model长期持有,不释放内存,就造成了花费更多的内存