初次接触MVC是ASP.NET MVC,早前一直编写aspx的我接触到MVC以后爱的死去活来,深深的被它灵动简洁的思想所震撼,而当初的我js写的实在是渣,连jquery都用很差。也从未想到前端居然也可以导入MVC这么抽象性的东西。
近年,前端的需求也愈来愈重,过去后端的处理大多数都转移到了前端,而javascript又十分争气,一雪过去被鄙夷的耻辱。过去的javascript只是辅助页面的展示搞一些炫丽的特效,而如今已经演变的成为数据展示、加工的主力——随着前端任务繁重——前端MV*乘势而起。
MV*的思想中心很一致:UI和逻辑分离,提取数据模型。javascript
MVC核心:Model(模型),View(UI),Controller(控制器)css
它们的工做模型应该是:Controller=>Model=>View
html
MVVM核心:Model(模型),View(UI),ViewModel(视图模型)前端
它们的工做模型应该是:Model<=>ViewModel<=>View
java
让人比较困惑的是:MVVM中的Controller是什么?
ng和avalon都提供了名为Controller的方法,其实它们的意义和MVC一致:处理/加工Model。jquery
初次使用angularJS(如下简称ng)让我以为很迷茫,毕竟它颠覆了传统的DOM操做,过去的页面某个列表页的数据是拿到数据以后,要么封装成Model,要么写成一个方法而后展示到页面上,例以下面的代码:git
(function () { var data = [{ name: 'linkFly', blog: 'http://www.cnblogs.com/silin6/' }],//拿到数据 html = ['<ul>'], $container = $('#container'); //拼接为HTML data.forEach(function (item) { html.push('<li>', item.name, ' - ', item.blog); }); html.push('</ul>'); //展示到页面 $container.html(html.join('')); })();
而使用ng的代码以下:angularjs
<ul data-ng-repeat="item in datas"> <li>{{item.name}} - {{item.blog}} </li> </ul>
var app = angular.module('demo', []).controller('demoController', function ($scope) { //ViewModel双向绑定 $scope.datas = [{ name: 'linkFly', blog: 'http://www.cnblogs.com/silin6/' }]; });
MVVM的核心思想:不用再关注数据如何呈现到页面,由框架更新Model和View。github
ng也提供了自定义的ViewModel:directive(指令),代码以下:web
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="demo"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>ng demo</title> <script src="http://cdn.bootcss.com/angular.js/1.3.8/angular.min.js"></script> </head> <body data-ng-controller="demoController"> <hello data-ng-model="text"> <a href="javascript:;">i'm {{text}}</a> </hello> <script> var app = angular.module('demo', []).controller('demoController', function ($scope) { $scope.text = '***'; }).directive('hello', function () { //编写hello指令 return { restrict: 'E',//指定这个指令是Element类型的 scope: { text: '=ngModel' },//指定对象 link: function ($scope, $elem) { //注册事件 $elem.on('click', function () { //修改数据,双向绑定 $scope.text = $scope.text === '***' ? 'linkFly' : '***'; $scope.$apply(); }); } }; }); </script> </body> </html>
directive可让你的代码插件化/组件化,当你想要完成一个日历插件,可使用directive来实现,directive是ng中的ViewModel,再看ViewModel的本份:更新Model到View中。由于viewModel直面操做Model和View,因此全部的事件绑定、操做DOM的逻辑都应该在ViewModel/ng的directive中。
再看咱们以前MVVM的图:
ViewModel实现的双向绑定原理:从外部环境接收Model,呈现到View。从View接收行为(web中是浏览器的事件,例如鼠标点击之类的)再更新Model。
当理解了ViewModel的职责,我相信对于ng的directive理解将会很大。
而数据的处理/加工,应该仍然留在Controller中。MVVM的本质也只是注入了一层ViewModel。
其实主要源于ViewModel。
初次接触ng的directive深感迷茫,很大程度上对MVVM不理解。由于ng的directive的行为太过组件化,过了好久才明白其实咱们本身编写javascript也是组件化的,其实这也映射着更好的的web思想:Web components。
ng中的directive可让那些编码中习惯瞎灌一通代码的小伙伴尝到组件化的甜头,前提是大家须要经历痛苦的思想转换。
将来早晚要到来,Web components是趋势。
ViewModel的思惟颠覆了传统的javascript操做DOM的行为,迎合MVC的思想又可以让javascript的逻辑更加的清晰。为了迎接ViewModel,ECMAScript下下一个版本(ECMAScript 7,当前ECMAScript 5)准备了Object.observe()——监听/观察javascript对象:当被监听的对象发生变化,通知监听者,数据双向绑定的利器。
其实若是可以理解ViewModel,那么MVVM框架中不少事情都将能够获得很明确的答案,多数时候咱们老是在成型的编程思惟上去敲代码,当引入了一个框架,就意味着你要接受它的思想,然而颠覆一我的的思想是一件很困难的事情,毕竟咱们没法像盗梦空间里那样,悄悄注入一个想法,今后世界颠覆。
jQuery如此的卓越也体现了这点,在你刚开始使用它的时候就发现它并无侵入你的思想,你仍然能够用本身的思惟写出本身的代码,不得不说jQuery的理念得以让其在今天大行其道——专一DOM。
可能有人想说:"jQuery是库,不要跟框架并提。"
我知道。只是感叹一下。