注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看。
MVC
MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是将 M 和 V 的实现代码分离,从而使同一个程序可以使用不同的表现形式。
交互方式(所有通信都是单向的):
- View 传送指令到 Controller
- Controller 完成业务逻辑后,要求 Model 改变状态
- Model 将新的数据发送到 View,用户得到反馈
更详细的说明:
- 模型(Model) 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“ Model ”有对数据直接访问的权力,例如对数据库的访问。“Model”不依赖“View”和“Controller”,也就是说, Model 不关心它会被如何显示或是如何被操作。但是 Model 中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此 Model 的 View 必须事先在此 Model 上注册,从而,View 可以了解在数据 Model 上发生的改变。(比较:观察者模式(软件设计模式))
- 视图(View)能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。
- 控制器(Controller)起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。
MVC 模式在概念上强调 Model, View, Controller 的分离,各个模块也遵循着由 Controller 来处理消息,Model 掌管数据源,View 负责数据显示的职责分离原则,因此在实现上,MVC 模式的 Framework 通常会将 MVC 三个部分分离实现:
- Model 负责数据访问,较现代的 Framework 都会建议使用独立的数据对象 (DTO, POCO, POJO 等) 来替代弱类型的集合对象。数据访问的代码会使用 Data Access 的代码或是 ORM-based Framework,也可以进一步使用 Repository Pattern 与 Unit of Works Pattern 来切割数据源的相依性。
- Controller 负责处理消息,较高级的 Framework 会有一个默认的实现来作为 Controller 的基础,例如 Spring 的 DispatcherServlet 或是 ASP.NET MVC 的 Controller 等,在职责分离原则的基础上,每个 Controller 负责的部分不同,因此会将各个 Controller 切割成不同的文件以利维护。
- View 负责显示数据,这个部分多为前端应用,而 Controller 会有一个机制将处理的结果 (可能是 Model, 集合或是状态等) 交给 View,然后由 View 来决定怎么显示。例如 Spring Framework 使用 JSP 或相应技术,ASP.NET MVC 则使用 Razor 处理数据的显示。
一个通过 JavaScript 所实现的一个基础 MVC 模型,请注意的是:MVC 不是一种技术,仅是一种理念。
/** 模擬 Model, View, Controller */
var M = {}, V = {}, C = {};
/** Model 負責存放資料 */
M.data = "hello world";
/** View 負責將資料輸出到螢幕上 */
V.render = function (M) { alert(M.data); }
/** Controller 作為一個 M 和 V 的橋樑 */
C.handleOnload = function () { V.render(M); }
/** 在網頁讀取的時候呼叫 Controller */
window.onload = C.handleOnLoad;
ASP.NET MVC 中的 MVC 概念,和上面的概念稍微有些不同(有点像下面的 MVP),图示:
被动 MVC(ASP.NET MVC)与主动 MVC(传统 MVC)的区别在于:
- 模型对视图和控制器一无所知,它仅仅是被它们使用
- 控制器使用视图,并通知它更新数据显示
- 视图仅仅是在控制器通知它去模型取数据的时候它才这么做(视图并不会订阅或监视模型的更新)
- 控制器负责处理模型数据的变化
- 控制器可以包含对视图的渲染逻辑
资料来源:
MVP
Model-View-Presenter (MVP) 是使用者界面设计模式的一种,被广范用于便捷自动化单元测试和在呈现逻辑中改良分离关注点(separation of concerns)。
- Model 定义使用者界面所需要被显示的资料模型,一个模型包含着相关的业务逻辑。
- View 视图为呈现使用者界面的终端,用以表现来自 Model 的资料,和使用者命令路由再经过 Presenter 对事件处理后的资料。
- Presenter 包含着元件的事件处理,负责检索 Model 取得资料,和将取得的资料经过格式转换与 View 进行沟通。
- 各部分之间的通信,都是双向的。
- View 与 Model 不发生联系,都通过 Presenter 传递。
- View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
对 MVC 的改进的思想却是一样的:切断的 View 和 Model 的联系,让 View 只和 Presenter(原 Controller)交互,减少在需求变化中需要维护的对象的数量。
MVP 定义了 Presenter 和 View 之间的接口,让一些可以根据已有的接口协议去各自分别独立开发,以此去解决界面需求变化频繁的问题。
与“被动—MVC 模式(ASP.NET MVC)”很接近,区别在于“视图并不使用模型”。在 MVP 模式中视图和模型是完全分离的,他们通过Presenter进行交互。
Presenter 与控制器非常相似,但是它们也有一些的区别:
- Presenter处理视图发送过来的用户操作(在MVC中视图自己处理了这些操作)
- 它用更新过的数据去更新模型(在被动MVC中控制器只是通知视图去更新过的模型中去取新的数据,而主动MVC中模型通知视图去更新显示,控制器不需要做工作)
- 检查模型的更新(与被动MVC一样)
- (与MVC的主要区别)从模型中取数据然后将它们发送到视图中
- (与MVC的主要区别)将所做的更新告知视图
- (与MVC的区别)用Presenter渲染视图
MVP 的优势
- 模型与视图完全分离,我们可以修改视图而不影响模型
- 可以更高效地使用模型,因为所以的交互都发生在一个地方——Presenter 内部
- 我们可以将一个 Presener 用于多个视图,而不需要改变 Presenter 的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
- 如果我们把逻辑放在 Presenter 中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。
MVP 的问题
由于对视图的渲染放在了 Presenter 中,所以视图和 Persenter 的交互会过于频繁。还有一点你需要明白,如果 Presenter 过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么 Presenter 也需要变更了。
资料来源:
- MVC,MVP 和 MVVM 的图示
- MVC, MVP, MVVM 比较以及区别(下)
- 维基百科: MVP
- 从 Script 到 Code Blocks、Code Behind 到 MVC、MVP、MVVM
- MVP 模式与 MVC 模式
MVVM
MVVM(Model-View-ViewModel)的设计模式最早于 2005 年由微软的 WPF 和 Silverlight 架构师 John Gossman 在他的博客中提到。
MVVM 是 MVP 的演化版本,它们唯一的区别是,MVVM 采用双向绑定(data-binding):View 的变动,自动反映在 ViewModel,反之亦然。
MVVM 在使用当中,通常还会利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。所以,MVVM 模式有些时候又被称作:model-view-binder 模式。
这个图解准确地描述了什么是 MVVM:一个 MVC 的增强版,我们正式连接了视图和控制器,并将表示逻辑从 Controller 移出放到一个新的对象里,即 View Model。MVVM 听起来很复杂,但它本质上就是一个精心优化的 MVC 架构,
MVVM 模式和 MVC 模式一样,主要目的是分离视图(View)和模型(Model),有几大优点
- 低耦合:视图(View)可以独立于 Model 变化和修改,一个 ViewModel 可以绑定到不同的"View"上,当 View 变化的时候 Model 可以不变,当 Model 变化的时候 View 也可以不变。
- 可重用性:你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 view 重用这段视图逻辑。
- 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用 Expression Blend 可以很容易设计界面并生成 xaml 代码。
- 可测试:界面素来是比较难于测试的,而现在测试可以针对 ViewModel 来写。
MVVM 的问题:
- 数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
- 对于过大的项目,数据绑定需要花费更多的内存。
资料来源:
- MVC,MVP 和 MVVM 的图示
- MVVM 实践教程
- MVVM 介绍
- 被误解的 MVC 和被神化的 MVVM
- 不要听吹牛逼什么前端 MVVM 框架就是好,其实都是一帮没学好分层设计的搞出来的,让你彻底看清前端 MVVM 的本质
Angular.js
Angular.js 是一个 MV*(Model-View-Whatever,不管是 MVC 或者 MVVM,统归 MDV(model Drive View))JavaScript 框架。
Angular.js 是一款开源 JavaScript 库,由 Google 维护,用来协助单一页面应用程序运行的。它的目标是通过 MVC 模式(MVC)功能增强基于浏览器的应用,使开发和测试变得更加容易。
库读取包含附加自定义(标签属性)的 HTML,遵从这些自定义属性中的指令,并将页面中的输入或输出与由 JavaScript 变量表示的模型绑定起来。这些 JavaScript 变量的值可以手工设置,或者从静态或动态 JSON 资源中获取。
Angular.js 六大特性:
- 双向数据绑定
- 模板
- MVVM
- 依赖注入(Dependency Injection,DI)
- Directives(指令)
- 单元测试
Angular.js 简单示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
</head>
<body>
<div ng-app="">
<p>名字 : <input type="text" ng-model="name"></p>
<h1>Hello {{name}}</h1>
</div>
</body>
</html>
资料来源:
Knockout.js
Knockout.js 是一个 JavaScript 库(MVVM),它可以让你声明绑定元素和其对应的数据模型,达到你的UI和模型自动双向更新。
Knockout.js 使用 js 代码达到双向绑定的目的,类似 Silverlight/WPF 里的绑定一样,我们主要就是利用相关的特性进行开发的,极大地减少了代码开发量。
Knockout.js 是一个轻量级的 UI 类库,通过应用 MVVM 模式使 JavaScript 前端 UI 简单化。Knockout 是一个以数据模型(data model)为基础的能够帮助你创建富文本,响应显示和编辑用户界面的 JavaScript 类库。任何时候如果你的 UI 需要自动更新(比如:更新依赖于用户的行为或者外部数据源的改变),KO 能够很简单的帮你实现并且很容易维护。
Knockout.js 有如下4大重要概念:
- 声明式绑定 (Declarative Bindings):使用简明易读的语法很容易地将模型(model)数据关联到 DOM 元素上。
- UI界面自动刷新 (Automatic UI Refresh):当您的模型状态(model state)改变时,您的 UI 界面将自动更新。
- 依赖跟踪 (Dependency Tracking):为转变和联合数据,在你的模型数据之间隐式建立关系。
- 模板 (Templating):为您的模型数据快速编写复杂的可嵌套的 UI。
重要特性:
- 优雅的依赖追踪- 不管任何时候你的数据模型更新,都会自动更新相应的内容。
- 声明式绑定- 浅显易懂的方式将你的用户界面指定部分关联到你的数据模型上。
- 灵活全面的模板- 使用嵌套模板可以构建复杂的动态界面。
- 轻易可扩展- 几行代码就可以实现自定义行为作为新的声明式绑定。
额外的好处:
- 纯 JavaScript 类库 – 兼容任何服务器端和客户端技术
- 可添加到Web程序最上部 – 不需要大的架构改变
- 简洁的 – Gzip 之前大约 25kb
- 兼容任何主流浏览器 (IE 6+、Firefox 2+、Chrome、Safari、其它)
- Comprehensive suite of specifications (采用行为驱动开发) - 意味着在新的浏览器和平台上可以很容易通过验证。
简单示例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" src="http://knockoutjs.com/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="http://knockoutjs.com/js/jquery.tmpl.js"></script>
<script type="text/javascript" src="http://knockoutjs.com/js/knockout-1.2.1.js"></script>
</head>
<body>
Choose a ticket class:
<select data-bind="options: tickets,
optionsCaption: 'Choose...',
optionsText: 'name',
value: chosenTicket">
</select>
</p>
<p data-bind="template: 'ticketTemplate'">
</p>
<script id="ticketTemplate" type="text/x-jquery-tmpl">
{{if chosenTicket}}
You have chosen <b>${ chosenTicket().name }</b>
($${ chosenTicket().price })
<button data-bind="click: resetTicket">Clear</button>
{{/if}}
</script>
<script type="text/javascript">
var viewModel = {
tickets: [
{ name: "Economy", price: 199.95 },
{ name: "Business", price: 449.22 },
{ name: "First Class", price: 1199.99 }
],
chosenTicket: ko.observable(),
resetTicket: function () { this.chosenTicket(null) }
};
ko.applyBindings(viewModel);
</script>
</body>
</html>
资料来源:
- Knockout 应用开发指南(完整版) 目录索引
- Knockout.js 入门
- 个人整理的 Knockout.js 文档,有兴趣的朋友可以直接下载!
- MVVM(Knockout.js) 的新尝试:多个 Page,一个 ViewModel
- 通过 Knockout.js + ASP.NET Web API 构建一个简单的 CRUD 应用
Backbone.js
Backbone.js 是一套 JavaScript 框架与 RESTful JSON 的应用程序接口。也是一套大致上符合 MVC 架构的编程范型。Backbone.js 以轻量为特色,只需依赖一套 Javascript 库即可运行。常被用来开发单页的互联网应用程序,以及用来维护网络应用程序的各种部分(例如多用户与服务器端)的同步。
Backbone 最适合的应用场景是单页面应用,并且页面上有大量数据模型,模型之间需要进行复杂的信息沟通。Backbone 在这种场景下,能很好的实现模块间松耦合和事件驱动。 其他适用产品还有微博,网易微博的前端设计也是和 Backbone 类似的一个结构。
Backbone.js 的适用场景非常广,无论是 Web-Page 还是 Web-App 都可以应用,但最合适的还是大型的 Web-App,对于中小型项目来讲 Backbone.js 的 MVC 结构还是有点臃肿了,用不好很容易 over design。Backbone.js 是非常典型的 MVC 框架,但是相对于传统的 server 端 MVC 来讲还是有一些特殊的地方的。
首先 Backbone 中的几大核心组件 View、Model、Collection、Router 中并没有 Controller。其实 v0.5 以前是有 Backbone.Controller 这个东西的,但由于做的根本不是 C 的事情,这个名字又太具有迷惑性了,后来改名叫做 Backbone.Router。而真正的 C 其实是 Backbone.View,但这个 View 其实是部分的 C(还有一部分在 Backbone.Router 中) + 部分的 V,由于前端的模板功能有限,很多应该在 template 中做的事情不得不被拿到 Backbone.View 中来实现。
其次,由于 MVC 的概念中认为 V 其实是永远不知道用户输入(鼠标、键盘事件等)的,C 是输入和 V 之间的连接,但在浏览器中这点其实是实现不了的,V 就是 HTML,而用户输入是基于 HTML 页面的,所以你可以忽略用户输入,把所有事件都导入到 C 去处理,但不代表 V 不知道这件事情。所以前端的 MVC 多少是对传统的 MVC 模型做了些改变的实现,近些日子更多的人转向 MVVM 就是这个原因。
Backbone.js 的优点:
- 代码质量比较高,通读一遍还是能学到不少东西的。
- 只做框架该做的事情,不做高大全的东西。所以很容易和其他的工具或框架整合。比如有人搞了 Bakcbone.js + Knockout.js 的 Knockback.js。
- 分层的结构很清晰,使得前端工程在扩展性和维护性上都可以进行有效控制。
Backbone.js 缺点:
- Model 结构比较简单,多对多、但对多的数据模型很难搞,用对象做属性也不行。
- 内存控制,View 很容易产生 memory leak 的问题,不过这也和代码的质量有关系,近期的更新有一些是针对这方面的。
资料来源:
React.js
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。
创造 React 是为了解决一个问题:构建随着时间数据不断变化的大规模应用程序。
React 两个主要的思想:
简单:仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
声明式 (Declarative):数据变化后,React 概念上与点击“刷新”按钮类似,但仅会更新变化的部分。
React 都是关于构建可复用的组件。事实上,通过 React 你唯一要做的事情就是构建组件。得益于其良好的封装性,组件使代码复用、测试和关注分离(separation of concerns)更加简单。
资料来源:
Ember.js
Ember.js 是 JavaScript 框架包中最新的成员之一。 它演变出了最初于 2007 年创建的 SproutCore 项目,Apple 在包括 MobileMe 在内的各种 web 应用程序中大量使用了该项目。 在 emberjs.com,Ember 被形容为 "一个 JavaScript 框架,用于创建可以消除样板并提供标准应用程序架构的大型 web 应用程序。" 它本身紧密集成了名为 Handlebars 的模板引擎,该引擎为 Ember 提供了其中一个最强大的功能: 双向数据绑定。 Ember 还提供了其他功能,比如状态管理(某个用户状态是已注销还是已登录)、自动更新模板(当底层数据发生变化时,您的 UI 也同样发生变化)以及计算属性 (firstName + lastName = fullName)。 Ember 经过一年可靠的开发后,已经成为一个强大的参与者。
Ember 只有一个依赖项—jQuery。 Ember 应用程序的样板 HTML 设置看起来应该与下面的代码类似。 请注意,jQuery 和 Ember 都从 CDN(内容交付网络)进行更新。 如果用户在早些时候访问需要这些文件的其他网站时已经下载过这些文件,这会加快用户的页面加载速度。
与 Ember.js 相比,Angular.js 更像一个研究项目。比如,来看看它们的学习文档:Ember.js 主要讨论模型、视图和控制器,而 Angular.js 指南要求你去学习一些类似于范围、指示符和 transclusion 方面的内容等。
引用示例:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-0.9.6.min.js"></script>
<script src="js/app.js"></script>
</head>
<body>
</body>
</html>
资料来源:
Avalon.js
Avalon.js 是一个功能强大,体积小巧的 MVVM 框架。它遵循“操作数据即操作 DOM”的理念,让你在代码里基本见不到一点 DOM 操作代码。DOM 操作全部在绑定后,交给框架处理。相当后端有了 ORM 一样,不用你手写 SQL,提高生产力!
与其它 js 框架相比,同样实现著名的 todos 功能,在所有 MV* 的实现中 avalon 是让用户写代码最少的。
与其他 MV* 相比,它不仅轻量,最低支持到 IE6,而且性能是最好的。
优势:
- 使用简单,在 HTML 中添加绑定,在 JS 中用 avalon.define 定义 ViewModel,再调用 avalon.scan 方法,它就能动了!
- 兼容到 IE6(其他 mvvm 框架, knockoutjs IE6, angularjs IE7, emberjs IE8, winJS IE9 )
- 没有任何依赖,只有 72K,压缩后 22K
- 支持管道符风格的过滤函数,方便格式化输出
- 局部刷新的颗粒度已细化到一个文本节点,特性节点
- 要操作的节点,在第一次扫描就与视图刷新函数相绑定,并缓存起来,因此没有选择器出场的余地。
- 让 DOM 操作的代码近乎绝迹
- 使用类似 CSS 的重叠覆盖机制,让各个 ViewModel 分区交替地渲染页面
- 节点移除时,智能卸载对应的视图刷新函数,节约内存
- 操作数据即操作 DOM,对 ViewModel 的操作都会同步到 View 与 Model 去。
与其他框架比较:
- 它体积更少,在主要的几个 MVVM 框架(拥有双向绑定机制),knockout 是三千多行,angularjs 1.6万, emberjs 2-3 万行, winjs 是几 M, kendoui 是几 M!
- 兼容情况,kendoui 与 knockoutjs IE6, angularjs IE7, emberjs IE8, winJS IE9
- 让用户写代码更少
- 上手难度,与 knockout 差不多,但借鉴了 angularjs 的,更为易用。
- 与 knockoutjs, angular, winjs 一样是使用动态模板,至少保持第一屏数据是真实的,对 SEO 友好。
- 源码也是它们中最易读的。简单的代码也意味着扩展调试等容易。
资料来源:
Vue.js
官方地址:http://vuejs.org/
Vue.js 尤雨溪老师写的一个用于创建 web 交互界面的库,是一个精简的MVVM。从技术角度讲,Vue.js 专注于 MVVM 模型的 ViewModel 层。它通过双向数据绑定把 View 层和 Model 层连接了起来。实际的 DOM 封装和输出格式都被抽象为了Directives 和 Filters。Vue.js 和其他库相比是一个小而美的库,作者的主要目的是通过一个尽量简单的 API 产生可反映的数据绑定和可组合的视图组件,感觉作者的思路非常清晰。
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此它非常容易学习,非常容易与其它库或已有项目整合。另一方面,在与相关工具和支持库一起使用时,Vue.js 也能完美地驱动复杂的单页应用。
优点:
- 简单:官方文档很清晰,比 Angular 简单易学。
- 快速:异步批处理方式更新 DOM。
- 组合:用解耦的、可复用的组件组合你的应用程序。
- 紧凑:~18kb min+gzip,且无依赖。
- 强大:表达式 & 无需声明依赖的可推导属性 (computed properties)。
- 对模块友好:可以通过 NPM、Bower 或 Duo 安装,不强迫你所有的代码都遵循 Angular 的各种规定,使用场景更加灵活。
缺点:
- 新生儿:Vue.js 是一个新的项目,2014 年 3 月 20 日发布的 0.10.0ReleaseCandidate 版本,目前 github 上面最新的是 0.11.4 版本,没有 angular 那么成熟。
- 影响度不是很大:google 了一下,有关于 Vue.js 多样性或者说丰富性少于一些有名的库。
- 不支持 IE8:哈哈不过 AngularJS 1.3 也抛弃了对IE8的支持,但是 @司徒正美 老师的 avalon 是支持 IE6+ 的,应该下了很多努力去优化。这一点对于那些需要支持 IE8 的项目就不好了,不过这也是 web 前端开发的一个趋势,像 IE 低版本就应该退出历史舞台了,通过改变我们的前端思维,而不是顺应那些使用老版本而不去升级的人。玉伯老师就说过一句话,我觉得说的非常好“这年头,支持 IE6、7 早就不再是特性,而是耻辱。努力推动支付宝全面不支持 IE6、7,期待更多兄弟加盟”。
总结:(1) 简洁 (2) 轻量 (3)快速 (4) 数据驱动 (5) 模块友好 (6) 组件化
简单示例:
// html
<body>
<div id="app">
<p>{{ note }}</p>
<input type="text" v-model="note">
</div>
</body>
// js
var vm = new Vue({
el: '#app',
data: {
note: ''
}
})
资料来源:
附 JavaScript MVC framework