首页 > 代码库 > MVVM框架对比
MVVM框架对比
MVVM框架对比
- MVC和MVP简介
- MVVM
- Vue.js、Angular.js、Ember、Backbone等框架对比
- 双向绑定原理
- Virtual DOM
前端由于发展比较迅速,框架的更新迭代也比较快,从最初的 backbone.js 到后来的Ember、Knockout、Angular.js, 再到现在的Vue.js、React。
MVC和MVP简介
- 视图(view):用户界面
- 控制器(controller):业务逻辑
- 模型(model):数据保存
通信方式如下:
- view传送指令到controller
- controller完成业务逻辑后,model改变状态
- model将新的数据发送到view,用户得到反馈
MVC在前端中的典型实践 Backbone
MVP
- MVP模式将controller改名为Presenter,同时改变了通信方向
- 各部分之间的通信,都是双向的。
- view与model不发生联系,都通过presenter传递。
- view非常薄,不部署任何业务逻辑,被称为被动视图,所有逻辑都部署在Presenter。
MVVM
- 唯一的区别是MVVM采用了双向数据绑定,view的变动自动反映在view-model。Vue.js、Angular、Ember都采用这种模式;
每一个框架的诞生都是为了解决客观存在的问题,所以架构是对客观不足的妥协。
那么这么多MVVM框架的诞生是为了解决什么问题?
- 如何处理数据的更新和界面的更新。
Vue.js、Angular、Ember、Backbone 对比
功能
作为构建应用的基础,框架必须具备一些重要的功能,比如,视图绑定、双向绑定、筛选、可计算属性、脏属性、表单验证等等
功能 | Vue | Angular | Backbone | Ember |
---|---|---|---|---|
可观察对象(observable) | y | y | y | y |
路由(routing) | y | y | y | y |
视图绑定(view binding) | y | y | - | y |
双向绑定(two way binding) | y | y | - | y |
部分视图(partial view) | y | y | - | y |
筛选列表视图(filtered list view) | y | y | - | y |
- 可观察对象:可以被监听是否发生变化的对象
- 路由
- 视图绑定:在视图中使用可观察对象,让视图随着可观察对象的变化而自动刷新
- 双向绑定
- 部分视图:包含其他视图的视图
- 筛选列表视图:用于显示根据某些条件筛选出来的对象视图
灵活性
有时候,框架配合一些现成的插件和库来使用,可能要比使用框架原生同类功能效果更好,而这种插件和库几乎遍地都是(不下数百个),又各有特色。因此,能够把这些库和插件整合到MVC框架中也非常重要。
Backbone是其中最灵活的一个框架,因为它的约定和主张最少。使用Backbone需要你自己作出很多决定。
Ember、Angular、Vue.js 也都还算灵活,可有时候你会发现,就算不喜欢它们的某些实现方法,你也只能默默忍受。 这是在选择Ember或Angular时必须考虑的。
上手难度
Vue.js
上手比较容易,官方文档比较清晰。专注于MVVM的ViewModel层,实际的DOM封装和输出格式都被抽象为了Directives和Filters。
Angular 4.0
一开始会让人大呼过瘾,因为可以利用它干好多意想不到的事,而且学习难度不高。乍一看让人觉得很简单。可是,进了门之后,你会发现后面的路还很长。应该说这个框架比较复杂,而且有不少标新立异之处。想看着它的文档上手并不现实,因为Angular制造的概念很多,而文档中的例子又很少。
Backbone
Backbone的基本概念非常容易理解。但很快你会发现它对怎么更好地组织代码并没有太多主张。为此,你得观摩或阅读一些教程,才能知道在Backbone中怎么编码最好。而且,你会发现在有了Backbone的基础上,还得再找一个库(比如Marionette或Thorax)跟它配合才能得心应手。正因为如此,我不认为Backbone是个容易上手的框架。
Ember
Ember的上手难度与Angular有一拼,我认为学习Ember比学习Angular总体上容易一些,但它要求你一开始就要先搞懂一批基本概念。而Angular呢,一开始不需要这么费劲也能做一些让人兴奋不已的事儿。Ember缺少这种前期兴奋点。
社区支持
能轻易找到参考资料和专家帮忙吗?
Backbone的社区很大,这是人所共知的事实。关于Backbone的教程也几乎汗牛充栋,StackOverflow和IRC社区非常热闹。
Angular和Ember社区也相当大,教程什么的同样不少,StackOverflow和IRC也很热闹,但还是比不上Backbone。
Vue的社区比较一般,可能是由于框架还处于发展阶段,还未达到上述几个框架的稳定和成熟。
有没有插件或库构成的生态系统?
Backbone的选择是最多的,可用插件俯拾皆是,这一点让其他框架都望尘莫及。Angular的生态圈加上Angular UI还是很令人瞩目的。我觉得Ember的下游生态虽然欠发达,但Ember本身很受欢迎, 所以前景十分乐观。
文件大小
Vue和Angular是唯二不需要其他库就能使用的,其他几个框架都需要依赖。
Backbone至少需要 Underscore 和 Zepto。虽然在Underscore中可以使用最小的模板来渲染视图,但多数情况下,还要借助更好的模板引擎,比如 Mustache 。
Ember 需要 jQuery 和 Handlebars。
Vue | Angular | Backbone | Ember |
---|---|---|---|
18kb | 80kb | 61kb | 269kb |
成熟度
这个框架成熟吗,经过实际检验了吗,有多少网站在用它呢?
使用Backbone的网站不计其数。最近两年,它的核心代码没怎么改过,这是成熟的一个重要标志。
Ember已经不是新框架了,但它的重大变更还是经常有,前几月刚刚稳定下来。因此,目前还不能说它是个成熟的框架。
Angular似乎比Ember更稳定,验证的示例也更多,但不能与Backbone相提并论。
Vue 属于一个新项目,2014-3-20 发布的0.10.0 Release Candidate版本。
双向绑定
this.showLoading = false
this.cmsData = http://www.mamicode.com/data
this.showDownload = data.template.isDownload
this.topBar.displaySharebutton = data.displaySharebutton
this.topBar.title = data.template.title
双向绑定的基本原理是通过属性的读写器来实现。
function Person() {
var name = ”;
var friends = [];
Object.defineProperty(this, ‘name’, {
get: function () {
console.log(‘get!’)
return name;
},
set: function (value) {
name = value;
friends.push(name)
}
});
this.getFriends = function() {
return friends;
};
}
Virtual DOM
最近一两年前端最火的技术莫过于ReactJS,即便你没用过也该听过,ReactJS由业界顶尖的互联网公司facebook提出,其本身有很多先进的设计思路,比如页面UI组件化、虚拟DOM等。
为什么需要虚拟DOM?
DOM是很慢的,其元素非常庞大,页面的性能问题鲜有由JS引起的,大部分都是由DOM操作引起的。如果对前端工作进行抽象的话,主要就是维护状态和更新视图;而更新视图和维护状态都需要DOM操作。其实近年来,前端的框架主要发展方向就是解放DOM操作的复杂性。
理解虚拟DOM
虚拟的DOM的核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作。这句话,也许过于抽象,却基本概况了虚拟DOM的设计思想。
- 提供一种方便的工具,使得开发效率得到保证;
- 保证最小化的DOM操作,使得执行效率得到保证;
“
//设置虚拟dom的相关属性
var VElement = function(tagName, props, children) {
//保证只能通过如下方式调用:new VElement
if (!(this instanceof VElement)) {
return new VElement(tagName, props, children);
}
//可以通过只传递tagName和children参数
if (util.isArray(props)) {
children = props;
props = {};
}
this.tagName = tagName;
this.props = props || {};
this.children = children || [];
this.key = props ? props.key : void 666;
var count = 0;
util.each(this.children, function(child, i) {
if (child instanceof VElement) {
count += child.count;
} else {
children[i] = ‘‘ + child;
}
count++;
});
this.count = count;
};
通过VElement,我们可以很简单地用js表示DOM结构。
var vdom = VElement(‘div‘, { ‘id‘: ‘container‘ }, [
VElement(‘h1‘, { style: ‘color:red‘ }, [‘simple virtual dom‘]),
VElement(‘p‘, [‘hello world‘]),
VElement(‘ul‘, [VElement(‘li‘, [‘item #1‘]), VElement(‘li‘, [‘item #2‘])])
]);
上面的javascript代码可以表示如下DOM结构:
<div id="container">
<h1 style="color:red">simple virtual dom</h1>
<p>hello world</p>
<ul>
<li>item #1</li>
<li>item #2</li>
</ul>
</div>
比对两棵DOM树的差异
在用JS对象表示DOM结构后,当页面状态发生变化而需要操作DOM时,我们可以先通过虚拟DOM计算出对真实DOM的最小修改量,然后再修改真实DOM结构(因为真实DOM的操作代价太大)。
- 如何比较两棵DOM树
function diff(oldTree, newTree) {
//节点的遍历顺序
var index = 0;
//在遍历过程中记录节点的差异
var patches = {};
//深度优先遍历两棵树
dfsWalk(oldTree, newTree, index, patches);
return patches;
} - 如何记录节点之间的差异
- 对真实DOM进行最小化修改
针对DOM的处理,可分为:
- 修改节点属性 PROPS
- 修改节点文本内容 TEXT
- 替换原有节点 REPLACE
- 调整子节点,包括移动、删除 REORDER
MVVM框架对比