MVC的JavaScript Web富应用开发——学习笔记(1)MVC和类

MVC是一种设计模式 它将应用划分为三个部分: 数据,展现和用户交互

一个事件的发生:
1 用户和应用产生交互
2 控制器的事件处理器被触发
3 控制器从模型中请求数据,并交给视图
4 视图数据呈现给用户
 
模型:
模型用来存放应用的所有数据对象
模型不必知晓视图和控制器的细节,模型只需要包含数据以及直接和这些数据相关的逻辑,模型是最应该从应用中解耦出来的部分。
当控制器从服务器抓取数据或创建新的纪录时,它就将数据包装成模型实例,也就是说数据是面向对象的,任何定义在这个数据模型上的函数或逻辑都可以被直接调用。
 
视图:
视图层是 呈现给用户的,用户与之产生交互。在JavaScript应用中,视图大多数是由HTML,CSS和JavaScript模板组成。除了简单的条件语句外,视图不应该包含任何其他逻辑。
将逻辑混入视图之中是编程的大忌。
这并不是说MVC不允许包含视觉呈现相关的逻辑,只要这部分逻辑没有定义在视图之内即可。
我们将视觉呈现逻辑归类为“视图助手”:和视图有关的独立的小型工具函数。
 
 
控制器:
控制器是模型和视图之间的纽带。控制器从视图获得事件和输入,对它们进行处理,并相应的更新视图。当页面加载时,控制器会给视图添加事件监听,比如监听表单提交或按钮点击。然后当用户和应用产生交互时,控制器重的事件触发器就开始工作了。
 
JavaScript中的类
当使用new关键字来调用构造函数时,执行上下文从全局对象window变成一个空的上下文,这个上下文代表一个新生成的实例。
默认情况下,如果你的构造函数中没有返回任何内容,就会返回this——当前的上下文。
 
创建类
创建自己的类模拟库
 1   var Class = function(){
 2     var klass = function(){
 3       klass.init.apply(this, arguments);   
 4     }
 5     klass.prototype.init() = function(){};
 6     return klass;
 7   };
 8   var Person = new Class;
 9 
10   Person.prototype.init = function() {
11     //基于Person的初始化内容
12   }
13 
14   var person = new Person;
 
给类的prototype起一个别名fn,写起来也方便。
1   Person.fn = Person.prototype;
2   Person.fn.run = function(){/*......*/};
 
给类库添加方法
我们采用另外一种方法添加属性
 1     klass.extend = function(obj){
 2       var extended = obj.extended;
 3       for( var i in obj){
 4         klass[i] = obj[i];
 5       }
 6       if( extended )
 7         extended(klass);
 8     };
 9 
10     klass.include = function(obj){
11       var included = obj.included;
12       for( var i in obj){
13         klass[i].fn = obj.[i];
14       }
15       if( included )
16         included(klass);
17     }
18  
19   var Person = new Class;
20   Person.extend({
21        find: function(id){/*...*/},
22        exists: function(id){/*....*/}
23   });
24   var person = Person.find(1);
 
同样,这里支持回调,即将属性传入后会触发这个回调:
1   Person.extend({
2      extended: funtcion(klass) {
3           console.log(klass,"was extended");
4      }
5   });
 
这种写法之美在于它可以支持模块。
1   var ORMModule = {
2      save: funtction() {
3           //共享的函数
4      }
5   };
6   Person.include(ORMModule);
7   Asset.include(ORMModule);
 
原型
JavaScript是基于原型的编程语言,原型用来区别类和实例,原型是一个“模板”对象,它上面的属性被用做初始化一个新对象。任何对象都可以作为另一个对象的原型对象,以此来共享属性。可以理解为某种形式的继承。
当你读取一个对象的属性时,JavaScript首先会在本地对象中查找属性,如果没有找到,会在对象的原型中查找,若还未找到则会继续查找原型的原型,知道找到Object.prototype。如果找到就返回值,否则返回undefined。
换句话说,如果你给Array.prototype添加了属性,那么所有的JavaScript数组都有了这些属性。
 
给类库添加继承
现在来给我们定义的“类”库添加继承,
 1   var Class = function(parent){
 2     var klass = function(){
 3       klass.init.apply(this, arguments);   
 4     }
 5 
 6     if(parent){
 7       var subclass = function () {};
 8       subclass.prototype = parent.prototype;
 9       klass.prototype = new subclass;
10     }
11 
12     klass.prototype.init() = function(){};
13     klass.fn = klass.prototype;
14     klass.fn.parent = klass;
15     klass._super = klass.__proto__;
16 
17   /*
18      extend.....
19      include......
20   */
21 
22     return klass;
23   };
将parent传入Class构造函数,所有的子类则会共享一个原型。
 
函数调用
JavaScript中,函数也是一个对象,然后不同的是,它是可以调用的,函数内上下文取决于调用它的位置。
除了使用方括号调用函数外,还可以用apply和call调用。
function.apply(this,[1,2,3]);
function.call(this,1,2,3);
function(1,2,3){}
JavaScript中允许更换上下文是为了共享状态,尤其是在事件回调中。
若要访问原始上下文,则可将原始上下文的this值存入一个局部变量中。
使用call和apply还有一个功能,就是将调用委托给另一个调用
即在获得参数args=jQuery.makeArray(arguments);和上下文this时, 可以调用其他部分功能相同的函数实现同样功能function.apply(this,args);
其中arguments并不是真正的数组,需要通过jQuery的makeArray转换得到可以使用的数组。
 
控制类库的作用域
 1   var Class = function(parent){
 2       var klass = function(){
 3         this.init.apply(this, arguments);
 4       };
 5       klass.prototype.init = function(){};
 6       klass.fn = klass.prototype;
 7       // 添加一个proxy 函数
 8       klass.proxy = function(func){
 9           var self = this;
10           return(function(){
11               return func.apply(self, arguments);
12           });
13       }
14       // 在实例中也添加这个函数
15       klass.fn.proxy = klass.proxy;
16       return klass;
17   };
 
ECMAScript中加入了bind()函数用以控制调用的作用域
有的浏览器不支持bind,所以我们也可以自己手动实现bind()
 1   if(!Function.prototype.bind){
 2     Function.prototype.bind = function(obj) {
 3       var slice = [].slice;
 4       args = slice.call(arguments,1),
 5       self = this,
 6       nop = function() {},
 7       bound = function() {
 8         return self.apply( this instanceof nop ? this:(obj || {}),
 9           args.concat(slice.call(arguments)));
10       };
11       nop.prototype = self.prototype;
12       bound.prototype = new nop;
13       return bound;
14     };
15   }
推荐es5-shim
 
添加私有函数
很多开发者习惯在私有属性下面加_, 便于区分。但是方法太丑陋。。。
我们可以利用JavaScript匿名函数来创建私有作用域。
1   var Person = function(){};
2   (function{
3     var findById = function(){ /*....*/};
4 
5     Person.find = function(id) {
6       if( typeof id = = "integer")
7         return findById(id);
8     };
9   })();
 
类库的方法:
介绍了HJS和Spine。
原文地址:https://www.cnblogs.com/oneX/p/3662918.html