转载请注明翻译者为:曲奇饼, http://quqibing.iteye.com
在历史上第一次,Ext JS的经历了一个在基础上的巨大重构,这就是新的类系统。新架构的基础几乎每一个都是建立在Ext JS4.x重写的单个类上,因此在开始编码之前理解这个类系统是很重要的。
本手册适用于任何希望创造新的或扩大在现有的Ext JS 4.x类的开发者。它分为4个部分:
Ext JS 4有 300多个类。我们有超过20万开发者的巨大社区,他们来自世界各地,有各种编程背景。在这种规模的框架中,我们面对的一个巨大挑战就是提供一个共同的代码架构。这个架构要求:
JavaScript是一个没有类的,原型为导向(prototype-oriented)的语言 。因此, JavaScript语言本质上最强大的功能之一是灵活性。它可以使用许多不同的编码风格和技巧,以许多不同的方式做同样的工作。然而,该功能也是不可预知的成本。如果没有一个统一的结构,JavaScript代码会真的很难理解,维护和再利用 。
另一方面,基于类(Class-based)编程,仍然停留OOP的最流行的模式。基于类的语言,通常需要强类型,提供封装,标准的编码约定。通常使得开发者坚持一个大原则,编写的代码更可能是可预见的、可延伸和可扩展的。然而,他们却不具有JavaScript这样的语言的动态能力。
每种方法都有其自身的利弊,我们能否对各方都去其糟粕,取其精华?答案是肯定的,我们已经在Ext JS 4的解决方案中实现了。
使用一致的命名约定作为所有类的代码基础,而命名空间和文件名有助于保持你的代码的组织,结构化和可读性。
类名只能包含字母和数字字符 。数字是允许的,但在大多数情况下不推荐使用,除非是表达一个技术术语(比如Base64)。不要使用下划线、连字符,或任何其他非字母数字字符。例如:
MyCompany.useful_util.Debug_Toolbar不推荐
MyCompany.util.Base64可接受
类名应该被组织到适当的和正确的命名空间和包中,用(.)分隔包。最低限度,应该有一个独特的顶级命名空间的类名称。例如:
MyCompany.data.CoolProxy MyCompany.Application
顶级的命名空间和实际类名应该用驼峰命名法,其他名称应全部小写。例如:
MyCompany.form.action.AutoLoad
除了Sencha 发布的类以外,都不应该使用Ext作为顶级命名空间 。
缩略语也应该遵循上面列出的驼峰命名法。例如:
Ext.data.JsonProxy 来替代 Ext.data.JSONProxy MyCompany.util.HtmlParser,来替代MyCompary.parser.HTMLParser MyCompany.server.Http,来替代 MyCompany.server.HTTP
由于类名称直接映射到存储这些类的文件路径上。因此,每个文件只能有一个类。例如:
Ext.MessageBox.YES =“YES” Ext.MessageBox.NO =“NO” MyCompany.alien.Math.PI =“3.14”(译者:原文写成了4.13 )
如果您曾经使用过任何以前版本的Ext JS,你肯定熟悉Ext.extend创建一个类:
var MyWindow = Ext.extend(Object, { ... });
除了直接继承,遵循这种做法很容易创建从另一个类继承的新类。但是,我们没有为类的创建提供其他方面流畅的API,如配置,静态和混入。我们马上就会修订这些条目。
让我们看看另一个例子:
My.cool.Window = Ext.extend(Ext.Window, { ... });
在这个例子中,我们希望在自己的命名空间创建新类,并使其从Ext.Window继承。我们需要解决两方面的问题:
第一个问题通常由Ext.namespace(别名为Ext.ns)解决。该方法通过对象/属性树递归横向创建他们,如果他们不存在。你不得不需要记住在代码里添加Ext.extend。
Ext.ns('My.cool'); My.cool.Window = Ext.extend(Ext.Window, { ... });
然而,第二个问题不容易解决,因为 Ext.Window可能取决于它直接/间接继承的许多其他类。反过来,这些依赖关系可能还依赖于其他类的存在。出于这个原因,Ext JS 4之前编写的应用程序通常包括整个库EXT - all.js,即使开发者可能只需要一个框架的一小部分。
Ext JS 4消除了所有这些缺点:创建类时你只需要记住Ext.define这一个方法。它的基本语法如下:
Ext.define(className, members, onClassCreated);
members
是一个对象,表示一个类成员的键-值对的集合 例如:
Ext.define('My.sample.Person', { name: 'Unknown', constructor: function(name) { if (name) { this.name = name; } return this; }, eat: function(foodType) { alert(this.name + " is eating: " + foodType); return this; } }); var aaron = Ext.create('My.sample.Person', 'Aaron'); aaron.eat("Salad"); // alert("Aaron is eating: Salad");
注意,我们创建了一个新的实例My.sample.Person使用Ext.create()方法。我们可以用 new关键字(new My.sample.Person() )。然而,建议总是使用 Ext.create并养成习惯,因为它有动态加载的好处。对于动态加载的详细信息,请参阅“入门指南”
在Ext JS 4中,我们引入一个专用的config属性,这个属性在类创建前就可以由Ext.class的强大的预处理器处理,这些特性包括:
Ext.define('My.own.Window', { /** @readonly */ isWindow: true, config: { title: 'Title Here', bottomBar: { enabled: true, height: 50, resizable: false } }, constructor: function(config) { this.initConfig(config); return this; }, applyTitle: function(title) { if (!Ext.isString(title) || title.length === 0) { alert('Error: Title must be a valid non-empty string'); } else { return title; } }, applyBottomBar: function(bottomBar) { if (bottomBar && bottomBar.enabled) { if (!this.bottomBar) { return Ext.create('My.own.WindowBottomBar', bottomBar); } else { this.bottomBar.setConfig(bottomBar); } } } });
这是一个如何使用它的例子:
var myWindow = Ext.create('My.own.Window', { title: 'Hello World', bottomBar: { height: 60 } }); alert(myWindow.getTitle()); // alerts "Hello World" myWindow.setTitle('Something New'); alert(myWindow.getTitle()); // alerts "Something New" myWindow.setTitle(null); // alerts "Error: Title must be a valid non-empty string" myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100
可以定义静态成员使用statics config
Ext.define('Computer', { statics: { instanceCount: 0, factory: function(brand) { // 'this' in static methods refer to the class itself return new this({brand: brand}); } }, config: { brand: null }, constructor: function(config) { this.initConfig(config); // the 'self' property of an instance refers to its class this.self.instanceCount ++; return this; } }); var dellComputer = Computer.factory('Dell'); var appleComputer = Computer.factory('Mac'); alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts "Mac" alert(Computer.instanceCount); // Alerts "2"
Ext JS 4包括一些有用的功能,这将有助于您调试和错误处理。
throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');