当前位置: 首页 > 图文教程 > 网络编程 > Javascript > MooTools教程(告诉你为什么学Mootools)

Javascript
JS getMonth()日期函数的值域是0-11
jQuery 处理网页内容的实现代码
jQuery 树形结构的选择器
jQuery 处理表单元素的代码
JQuery 动画卷页 返回顶部 动画特效(兼容Chrome)
JavaScript 10件让人费解的事情
类似GMAIL的Ajax信息反馈显示
两个比较有用的Javascript工具函数代码
JavaScript Timer实现代码
JavaScript 学习技巧
JavaScript 题型问答有答案参考
js删除select中重复项的实现代码
javascript中的链式调用
JavaScript DOM学习第一章 W3C DOM简介
JavaScript DOM 学习第二章 编辑文本
JavaScript DOM 学习第三章 内容表格
JavaScript DOM学习第四章 getElementByTagNames
JavaScript DOM 学习第五章 表单简介
JavaScript DOM学习第六章 表单实例
JavaScript DOM 学习第七章 表单的扩展

Javascript 中的 MooTools教程(告诉你为什么学Mootools)


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-28   浏览: 199 ::
收藏到网摘: n/a

MooTools是一个简洁,模块化,面向对象的JavaScript框架。它能够帮助你更快,更简单地编写可扩展和兼容性强的JavaScript代码。Mootools跟prototypejs相类似,语法几乎一样。但它提供的功能要比prototypejs多,而且更强大。比如增加了动画特效、拖放操作等等。建议大家可以用它来代替prototypejs。

我为什么选择mootools,抛弃了prototype. (mootools 与 prototype 核心代码分析)

===========================================
前言
===========================================

最近喜欢上了mootools(相见恨晚啊),在公开表示了对他的偏爱.
很多朋友都问我为什么要移情别恋,其实理由还是蛮多的.

今天在这里打算列举出一部分.让更多的朋友能够了解一下mootools,也希望有更多的朋友喜欢上他.

文章的标题注定了我会更多的讲述 mootools比prototype好的地方,
希望大家不要被我的误导,以为mootools处处都比prototype好.
mootools还是有一些不足的.

本次对比针对 mootools 1.11版 和 prototype 1.51版,
只比较了一些核心代码,其他的工具方法,辅助函数不再本文讨论之内.

开始前,再次重申一遍:我曾经很爱prototype,而且我将永远都会用"伟大"来形容它.

好 下面对比正式开始 (
mootools以下简称moo.
本文所引用的代码, 只是起到说明作用,不保证他们都可以被正确的执行.
同时为了使本文简洁一些,引入的 一些 moo和prototype的代码也只是片段或是伪代码.
)

===========================================
一. 类机制
===========================================

js里的类实际上就是function.
如果不使用任何框架和组件,那么想创建一个自己类也不是难事,方法如下:

 

 

Java代码

 

  1. var PersonClass=function(name,gender){   
  2.     this.name=name;   
  3.     this.gender=gender;   
  4.     alert("My name is "+this.name);   
  5. }   
  6.   
  7. var myGirlFriend=new PersonClass('Vickey','female');  

 

var PersonClass=function(name,gender){	this.name=name;	this.gender=gender;	alert("My name is "+this.name);
}
var myGirlFriend=new PersonClass('Vickey','female');

执行 后, 会创建一个PersonClass类的实例myGirlFriend, 并执行function内的语句.
那些语句可以理解为是类的构造函数.

Prototype
现在来看看在prototype的帮助下如何去定义这个类:

 

 

Java代码

 

  1. var PersonClass = Class.create();   
  2.   
  3. PersonClass.prototype.initialize=function(name,gender){   
  4.     this.name=name;   
  5.     this.gender=gender;   
  6.     alert("My name is "+this.name);   
  7. };   
  8.   
  9. var myGirlFriend=new PersonClass('Vickey','female');   
  10.   
  11. //如果想给类增加属性和方法时使用    
  12. PersonClass.prototype.XXX=...;   
  13. //或者是使用 prototype提供的    
  14. Object.extend(PersonClass.prototype, {...} );  

 

var PersonClass = Class.create();
PersonClass.prototype.initialize=function(name,gender){	this.name=name;	this.gender=gender;	alert("My name is "+this.name);
};
var myGirlFriend=new PersonClass('Vickey','female');
//如果想给类增加属性和方法时使用
PersonClass.prototype.XXX=...;
//或者是使用 prototype提供的
Object.extend(PersonClass.prototype, {...} );


(关于Object.extend稍后在对比继承机制时再细说.)

再来看看prototype是实现类机制的核心代码.

 

 

Java代码

 

  1. var Class = {   
  2.   create: function() {   
  3.     return function() {   
  4.       this.initialize.apply(this, arguments);   
  5.     }   
  6.   }   
  7. }  

 

var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }
}


通过看代码不难看出,prototype的Class实际上只是帮助我们抽象出了"类的构造函数".
而当我们在prototype的这种机制下进行类的定义时,实际上带来的好处是非常有限的.
prototype的Class只是从结构对我们的类进行了重新规划. 而这样的规划意义并不是很大.
而且prototype带有强制性,即, initialize 是必须要定义的.
实际上这里存在一个缺陷, Class应该提供一个默认的initialize(一个空函数就好),
或者是在create返回的function里进行必要的判断.
(prototype1.6的类机制变化比较大,但是还没仔细研究过,所以不敢轻易评论).

Mootools

现在来看看在 moo的帮助下如何去定义一个类:

 

 

Java代码

 

  1. var PersonClass = new Class( {   
  2.     initialize: function(name,gender){   
  3.         this.name=name;   
  4.         this.gender=gender;   
  5.         alert("My name is "+this.name);   
  6.     }   
  7. });   
  8. var myGirlFriend=new PersonClass('Vickey','female');  

 

var PersonClass = new Class( {	initialize: function(name,gender){	this.name=name;	this.gender=gender;	alert("My name is "+this.name);	}
});
var myGirlFriend=new PersonClass('Vickey','female');


其中类的 initialize 不是必须的.
如果你想给 PersonClass 增加属性和方法,你可以在new Class的参数里直接以 json方式定义.
也可以使用 如下方式

 

 

Java代码

 

  1. PersonClass.implement ({    
  2.     age:0 ,   
  3.     getName : function() {return this.name;}   
  4. } , {...}, ..... );  

 

PersonClass.implement ({	age:0 ,	getName : function() {return this.name;}
} , {...}, ..... );


implement支持多个{}.关于implement稍后在对比继承机制时再细说.



在来看一下moo类机制的一些核心代码.

 

 

Java代码

 

  1. var Class = function(properties){   
  2.     var klass = function(){   
  3.         return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;   
  4.     };   
  5.     $extend(klass, this);   
  6.     klass.prototype = properties;   
  7.     klass.constructor = Class;   
  8.     return klass;   
  9. };   
  10.   
  11. Class.prototype = {   
  12.     extend: function(properties){   
  13.         var proto = new this(null);   
  14.         for (var property in properties){   
  15.             var pp = proto[property];   
  16.             proto[property] = Class.Merge(pp, properties[property]);   
  17.         }   
  18.         return new Class(proto);   
  19.     },   
  20.     implement: function(){   
  21.         for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);   
  22.     }   
  23.   
  24. };  

 

var Class = function(properties){	var klass = function(){	return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;	};	$extend(klass, this);	klass.prototype = properties;	klass.constructor = Class;	return klass;
};
Class.prototype = {	extend: function(properties){	var proto = new this(null);	for (var property in properties){	var pp = proto[property];	proto[property] = Class.Merge(pp, properties[property]);	}	return new Class(proto);	},	implement: function(){	for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);	}
};

代码的具体原理就不细说了.大家在moo的Class里看到了 extend 和implement,那下面就来具体说一说moo和prototype的 继承机制吧.

===========================================
二. 继承机制
===========================================

Prototype
prototype提供的继承很简单.

 

 

Java代码

 

  1. Object.extend = function(destination, source) {   
  2.   for (var property in source) {   
  3.     destination[property] = source[property];   
  4.   }   
  5.   return destination;   
  6. }  

 

Object.extend = function(destination, source) { for (var property in source) { destination[property] = source[property]; } return destination;
}

他只是把source里的属性赋给destination,同时会覆盖destination里的同名属性.
他可以用于对象,也可以用于类,当要实现类的继承时,destination要使用 MySubClass.prototype.

prototype的继承机制可以说是非常薄弱的.

Mootools

moo提供了三种继承机制:

首先他也提供了简单的继承机制:
Objcet.extend (注意,不是上面代码中 Class 里的 extend)
他的代码如下

 

 

Java代码

 

  1.   
  2. var $extend = function(){   
  3.     var args = arguments;   
  4.     if (!args[1]) args = [this, args[0]];   
  5.     for (var property in args[1]) args[0][property] = args[1][property];   
  6.     return args[0];   
  7. };   
  8. Object.extend = $extend;  

 

var $extend = function(){	var args = arguments;	if (!args[1]) args = [this, args[0]];	for (var property in args[1]) args[0][property] = args[1][property];	return args[0];
};
Object.extend = $extend;


他的使用方法和 prototype 完全一样.

但是大家可能注意到了 这句 if (!args[1]) args = [this, args[0]]; 这句的纯在使得下面的代码写法成为可能.

 

 

Java代码

 

  1. var myObjcet={....};   
  2. myObjcet.extend=$extend;   
  3. myObjcet.extend(objA);   
  4. myObjcet.extend(objB);   
  5. myObjcet.extend(objC);  

 

var myObjcet={....};
myObjcet.extend=$extend;
myObjcet.extend(objA);
myObjcet.extend(objB);
myObjcet.extend(objC);

简单的一句话,让extend的用法增加了更多的灵活性,不得不赞一个了!!!



下面说说重点, moo的类里的extend和 implement
先说 implement,之前已经说了一些了

 

 

Java代码

 

  1. var MyClassA = new Class();   
  2. MyClassA.implement( { methodA : function() {... } }  );  

 

var MyClassA = new Class();
MyClassA.implement( { methodA : function() {... } } );

执行后 MyClassA 将拥有 methodA.

implement用来向类中添加属性和方法(会覆盖同名属性和方法),相当于
Object.extend (MyClassA.prototype , {... } )
但是Object.extend 不支持多个source,implement可以,示例如下:
MyClassA.implement( objA , objB, objC ... );

下面来看看moo的Class.extend.
moo的Class.extend才是我们期待的真正的"类继承",看一下官方的示例

 

 

Java代码

 

  1. var Animal = new Class({   
  2.     initialize: function(age){   
  3.         this.age = age;   
  4.     }   
  5. });   
  6. var Cat = Animal.extend({   
  7.     initialize: function(name, age){   
  8.         this.parent(age); //will call the previous initialize;   
  9.         this.name = name;   
  10.     }   
  11. });  

 

	var Animal = new Class({	initialize: function(age){	this.age = age;	}	});	var Cat = Animal.extend({	initialize: function(name, age){	this.parent(age); //will call the previous initialize;	this.name = name;	}	});

看那个parent() !!!!
通过moo的Class.extend实现的继承提供一个关键的方法 parent().
使用他你可以调用父类中的同名方法,好像java里的super一样.
这个示例已经可以说明一切了.

关于prototype和moo的类机制和继承机制的对比就到这里,孰优孰劣大家心里应该有数了吧.

===========================================
三.抽象对象
===========================================

再来看一看"抽象对象". 这个虽然对于开发人员来说用处不大,但还是对比一下吧,小细节也能看出作者的用心.

Prototype
prototype的抽象对象很简单
var Abstract = new Object();
具体的意义不大.

Mootools
moo的的抽象对象相对更完善一些.

 

 

Java代码

 

  1. var Abstract = function(obj){   
  2.     obj = obj || {};   
  3.     obj.extend = $extend;   
  4.     return obj;   
  5. };  

 

var Abstract = function(obj){	obj = obj || {};	obj.extend = $extend;	return obj;
};


支持自定义抽象(以参数形式传入),同时会为抽象对象自动添加extend方法.

===========================================
四. 关于 $()
===========================================

Prototype
prototype的$大家都比较熟悉了, 工作原理就是
通过id取得一个页面元素(或者直接传入一个页面元素对象),然后给他增加一些prototype提供的方法和属性,来方便开发人员对页面元素的使用.

Mootools
moo在这方面做的差不多.
不同的主要有两点, 首先moo为页面元素增加的方法和属性与prototype的不同(这个稍后会介绍),另外一个不同是moo的$兼具了对象管理的一个功能.
他引入了一个  Garbage 类, 来对页面元素进行一个统一的管理和回收(主要是回收).
可以更好的减少js(或浏览器)造成的内存泄露等问题.

具体的大家可以看一下代码,在这里就不详细说明了.



===========================================
五.关于 Array Enumerable Hash
===========================================

prototype 和 moo 都提供了集合迭代方法 (each)
这个网上已经有一篇不错的对比文章,我就不在这里重复了
http://blog.fackweb.cn/?p=50.

moo的 forEach/each方法: function(fn, bind){..}
那个bind 结合代码 和 上面那篇文章, 大家应该可以很好的看出来prototype和moo的不同与优劣.

prototype里面有 Enumerable 的概念,moo没有.
但是我个人一直觉得 Enumerable 比较鸡肋.
在实际开发中,很少使用.
Enumerable的功能完全可以 用普通json对象 或者是 Hash来实现.
moo的作者也许同样这么认为.所以 不再 设置一个 鸡肋的 Enumerable类.
但是请大家放心, Enumerable 能做的事情, 在moo里也能完成.

可以理解为

moo的 Array +  Hash +{} 完全可以接替 prototype的 Array + Enumerable + Hash +{}
当然对于一些工具方法两者提供的都不太一样,不好比较,但是那些方法都是附属品.
我们完全可以自己来实现,所以不在这次的比较范畴之内.

===========================================
六. 关于 Element
===========================================

两者的 Element 从作用上看类似.都是一种对页面元素的包装,为页面元素添加了一些诸如 addEvent remove style之类的方法.
但是大家通过看代码可以发现 moo的实现明显更简洁 更OO.

同时还有一个关键的不同,prototype又提取出了一个Form对象,里面包含了很多表单相关的方法.
同时还衍生出了 serializeElements Method 等等很多类和方法,代码瞬间变得异常复杂和难以琢磨.

而moo中没有Form对象,在moo中,Form本身就是一个Element 他没什么特别的,这样的思想类似components模式
普通Element具备的方法 Form 都应该具备, Form具备的方法 Element也都应该包含.form 和 其他页面元素没什么不同.
form元素只是一个包含了 input select textarea等子元素,同时拥有action target等属性而已.
一个p 一个span 一个td... 同样可以包含input select textarea子元素,同样可以拥有.action target属性.
浏览器处理他们的方式可能不同,但是在moo面前,大家完全平等.

其实prototype里 form和普通页面元素几乎也是平等的,但是问题就是,既然是平等的,又何必硬生生的造出Form以及那么多的衍生物呢?

===========================================
七.Ajax
===========================================

Prototype
prototype的ajax实现主要是靠一个 Ajax类 来实现.(但是这个类形同虚设,大家更多的是和 Ajax.Request 类打交道.

先来看一个prototype下一个简单的ajax提交实例:

 

 

Java代码

 

  1. var myAjax = new Ajax.Request( url,{parameters: myData , onComplete: callBackFunction } );  

 

var myAjax = new Ajax.Request( url,{parameters: myData , onComplete: callBackFunction } );


其中 myData 可以是字符 : "name=Vickey&gender=female";
也可以是对象 { name : Vickey, gender : female }

Mootools
moo首先在将ajax机制分层.提取出了一个基类:XHR.
目前XHR有两个子类, 一个是 Ajax ,另一个是Json.Remote.

在moo下一个简单的ajax提交实例:

 

 

Java代码

 

  1. var myAjax =new Ajax(url, {data : myData , onComplete: callBackFunction  }).request();  

 

 var myAjax =new Ajax(url, {data : myData , onComplete: callBackFunction }).request();


大家可以看到request成为了Ajax对象的一个方法,这样的设计显然是更合理更自然 也更OO的.

而且关键的一点是,你可以提前创建好你需要的ajax对象.在需要发出请求时再发出请求.

 

 

Java代码

 

  1. var myAjax =new Ajax(...);   
  2. ....   
  3. myAjax.request();  

 

 var myAjax =new Ajax(...);
..... myAjax.request();


同时还有一个重要特性, request是支持参数的,这个参数就是你要提交的数据.

也就是说,你可以在new Ajax时不指定数据或者指定一个默认数据.
在提交的时候可以提交另一个data.如.

myAjax.request(yourData);

其中data可以是字符串,可以是对象, 也可以是一个页面元素.

要用ajax提交一个form 或者一个 p下的所有表单元素,只是改变一下 myData.
var myData= $("formID");  // var myData= $("pID");
然后就和普通的ajax提交完全一样了.

myAjax.request(myData);

当然还有更oo的方式 :
myData.send({onComplete: callBackFunction });

用后一种方式的时候要保证提交的元素有action属性,没有你就赋一个 myData.action=url.
prototype里如何实现这一功能呢??

Prototype
Form.request($("formID") ,{ onComplete: callBackFunction });

当然prototype里也可以类似moo的做法 , 只要让myData=$("formID").serialize(true) 就可以了.
但是这一个小小的不同,反映出了设计上的差距.

Mootools
moo的Json.Remote类,简单,但是很实用:

 

 

Java代码

 

  1. var jSonRemoteRequest = new Json.Remote( url , {onComplete:callBackFunction }).send({name: 'Vickey',gender: 'female' });  

 

	var jSonRemoteRequest = new Json.Remote( url , {onComplete:callBackFunction }).send({name: 'Vickey',gender: 'female' });


这个类和Ajax类的本质区别是,
他提交的是一个序列化后的 json字符串("{name: 'Vickey',gender: 'female' } "),而不是把 json对象转化成QueryString ("name=Vickey&gender=female");

===========================================
结束语
===========================================

写这篇文章不是要批评prototype,以我现在的水平还没那个资格.
只是和mootools对比后, prototype在设计上的不足立刻就显现了出来.

虽然prototype新版本变化很多,很多我上面提到的一些不足都改正了,而且也加入了很多以前不具备的新的特性.
但是prototype现在的发展停留在:"修补不足,增加功能"的阶段,而没有从设计上进行深层次的重构,所以我不认为他在mootools面前有足够的底气.

至于jquery我没有深入研究过,但是它的设计觉得完全是prototype风格的, 注意,我说的是设计风格,而不是代码风格.
代码上他可能写的更精妙,更有趣,但是设计上依然是prototype风格:薄弱的类机制,靠简单的extend支撑起整个系统.
JQuery在很多方面很出色,但是归根结底他和prototype走在一条路上,只是在有些方面他走的更快.

mootools并非完美无缺,但是至少现在他美的地方比prototype更多,缺的地方比prototype更少.

所以,我选择mootools. 你呢??

不要听评论,不要看介绍, 只要看看他们的源代码, 同时动手用他们写些东西, 你的答案自然会浮现出来.