Ext JS 4官方文档之三 -- 类体系概述与实践


Posted in Javascript onDecember 16, 2012

Ext JS 4从底层对类体系进行了重构,这是Ext JS历史上的第一次对类体系的巨大重构。新的架构几乎被应用到每一个Ext JS 4的类中,所以希望您在开始编码前能对它有一定的了解,这是非常重要的。
这篇手册适用于任何想创建新类或者继承Ext JS 4中现存类的开发人员,分为4部分:
第一部分: "概述" -- 解释了创建一个强健的类体系的必要性
第二部分: "命名规范" -- 讨论了对类、方法、属性、变量和文件的最佳命名规范
第三部分: "实践" -- 提供了详细的一步一步的代码示例
第四部分: "错误处理和调试" -- 提供了非常有用的关于如何处理异常的秘诀和技巧

一. 概述
Ext JS 4拥有超过300个类,迄今为止,我们已经有一个超过200,000开发者的庞大社区,他们来自世界各地的各种编程背景。对于如此大规模的一个框架,我们面临着一个巨大的挑战来提供一个通用的代码体系结构:
友好并易于学习
开发迅速,容易调试,部署简单
组织良好,可扩展和可维护
JavaScript是一个无类型的,面向原型的语言,这种语言最强大的特性之一就是灵活性。它可以通过各种不同的方法,使用各种不同的编码风格和技巧来完成同一个工作。然而,这种特性却带来了一个不可预见的代价,如果没有一个统一的结构,JavaScript代码就很难理解、维护和重用。
基于类的编程,换句话说,使用最流行的OOP模型。基于类的语言通常是强类型语言,提供了封装,并有标准的编码约定。一般情况下,让开发者遵循一组统一的编码规则,写的代码才更可能是可预测的,可扩展的和可延伸的。然而,它们却没有了像JavaScript这类语言一样的动态能力。
每种方法都有它们自己的优缺点,但是我们能否同时利用它们两者的优点部分,而隐藏它们的缺点部分呢?答案是肯定的,我们已经在Ext JS 4中实现了这个解决方案。

二. 命名规范
在你的代码中始终使用一致的基于类、命名空间和文件名的命名规范,这将有助于保持你的代码易组织、结构化和易读。
1) 类
类名可以只包含字母数字字符,数字在大多数情况下是不允许的,除非它们属于一个技术术语。不要使用下划线,连字符,或任何其他非字母数字字符。例如:
MyCompany.useful_util.Debug_Toolbar 是不可以的
MyCompany.util.Base64 是可以的
类名应该通过使用对象的点表达式(.)属性,从而放置到适当的命名空间中。至少,类名应该有一个唯一的顶层命名空间。例如:
MyCompany.data.CoolProxy
MyCompany.Application
顶层命名空间和类名都应该采用驼峰命名法,除此之外,其他的应该全部小写。例如:
MyCompany.form.action.AutoLoad
不是由Sencha的Ext JS发布的类不能使用Ext作为顶层命名空间。
缩略词也应该遵循上述的驼峰命名规范。例如:
Ext.data.JsonProxy 代替了 Ext.data.JSONProxy
MyCompany.util.HtmlParser 代替了 MyCompary.parser.HTMLParser
MyCompany.server.Http 代替了 MyCompany.server.HTTP
2) 源文件
类的名称直接映射到存储它们的文件路径中,因此,每一个文件只能有一个类,例如:
Ext.util.Observable 存储在 /to/src/Ext/util/Observable.js
Ext.form.action.Submit 存储在 /to/src/Ext/form/action/Submit.js
MyCompany.chart.axis.Numeric 存储在 /to/src/MyCompany/chart/axis/Numeric.js
路径/to/src是您的应用程序的类的根目录,所有类都应该放置在这个共同的根目录下。
3) 方法和变量
与类名类似,方法和变量名可以只包含字母数字字符,数字在大多数情况下是不允许的,除非它们属于一个技术术语。不要使用下划线,连字符,或任何其他非字母数字字符。
方法和变量名也应该总是驼峰式的,这也适用于缩略词。
示例:
可接受的方法名称: encodeUsingMd5(),getHtml()代替了getHTML(),getJsonResponse()代替了 getJSONResponse(), parseXmlContent()代替了parseXMLContent()
可接受的变量名称: var isGoodName, var base64Encoder, var xmlReader, var httpServer
4) 属性
类属性名完全遵循与上述的方法和变量相同的命名规范,除了静态常量。
静态类属性即常量应该全部大写,例如:
Ext.MessageBox.YES = "Yes"
Ext.MessageBox.NO = "No"
MyCompany.alien.Math.PI = "4.13"

三. 实践
1. 声明
1.1) 老的方法
如果您曾经使用过任何先前版本的Ext JS,您肯定很熟悉使用Ext.extend来创建类:
var MyWindow = Ext.extend(Object, { ... });
这种方法很容易创建一个继承自其他类的新类,然而除了直接继承,我们没有一个很好的API来创建类的其他方面,如配置,静态配置和混入类,我们稍后将详细回顾它们。
让我们看看另外一个例子:
My.cool.Window = Ext.extend(Ext.Window, { ... });
在这个示例中,我们希望创建一个新的具有命名空间的类,并让它继承Ext.Window,这里有两个问题需要解决:
My.cool 必须是已存在的命名空间对象,这样我们才能分配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,尽管可能仅仅只需要其中的很小一部分。
1.2) 新的方法
Ext JS 4消除了所有这些缺点,您只需要记得唯一的一个创建类的方法是:Ext.define,它的基本语法如下:
Ext.define(className, members, onClassCreated);
className: 类名
members 是一个大对象,代表了一个类成员的集合,是一系列的键-值对
onClassCreated 是一个可选的回调函数,当类的所有依赖项都准备好了,并且类被完全创建时,就会被调用。这个回调函数在很多情况下是很有用的,我们将在第四部分中深入讨论。
示例:

Ext.define('My.sample.Person',{ 
name: 'Unknown', 
constructor: function(name) {

 
if (name) {



 
this.name = name;


 
}}, 
eat: function(foodType) { 
alert(this.name + " is eating: " + foodType);
}}); 
var aaron = Ext.create('My.sample.Person', 'Aaron'); 
aaron.eat("Salad"); // alert("Aaron is eating: Salad");

注意,我们是用 Ext.create()方法创建了一个My.sample.Person的实例。当然我们也可以使用new 关键字(new My.sample.Person()),然而我们建议您养成总是使用 Ext.create 的习惯,因为它可以利用动态加载功能。更多关于动态加载的信息,请看Ext JS 4入门指南。

2. 配置
在Ext JS 4中,我们引入了一个专用的config属性,它会在类创建前,由强大的预处理器类 Ext.Class 进行处理,具有如下特性:
配置是从其他类成员完全封装的
每个config属性的getter和setter方法会在类原型中自动的生成,如果类里没有定义这些方法的话
同时,也会为每个config属性生成一个apply方法,自动生成的setter方法会在内部设置值之前调用这个apply方法。如果你想要在设置值之前运行自定义逻辑,就可以覆盖这个apply方法。如果apply没有返回值,setter方法将不会设置值。让我们看看下面的applyTitle方法:
下面的例子定义了一个新类:

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);
 }, 
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

3. 静态配置
静态配置成员可以使用statics属性来定义:

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 ++;
 }}); 
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包含了一些有用的特性,可以帮助你调试和错误处理:
你可以使用Ext.getDisplayName()方法来获取任何方法的显示名称,这是特别有用的,当抛出错误时,可以用来在错误描述里显示类名和方法名:
throw new Error('[' + Ext.getDisplayName(arguments.callee) + '] Some message here');
当错误从由Ext.define()定义的类的任何方法中抛出时,如果你使用的基于WebKit的浏览器(Chrome或者Safari)的话,你会在调用堆栈中看到方法名和类名。例如,下面是从Chrome中看到的堆栈信息:
Ext JS 4官方文档之三 -- 类体系概述与实践

Javascript 相关文章推荐
可输入的下拉框
Jun 19 Javascript
Ext 表单布局实例代码
Apr 30 Javascript
javascript getElementsByClassName 和js取地址栏参数
Jan 02 Javascript
Javascript Cookie读写删除操作的函数
Mar 02 Javascript
JavaScript中的数组操作介绍
Dec 30 Javascript
jQuery实现垂直半透明手风琴特效代码分享
Aug 21 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(三)
Sep 14 Javascript
深入理解Angularjs中的$resource服务
Dec 31 Javascript
浅谈vuex 闲置状态重置方案
Jan 04 Javascript
bootstrap中的导航条实例代码详解
May 20 Javascript
小程序使用wxs解决wxml保留2位小数问题
Dec 13 Javascript
vue数据更新UI不刷新显示的解决办法
Aug 06 Javascript
js弹出的对话窗口永远保持居中显示
Dec 15 #Javascript
JS函数实现动态添加CSS样式表文件
Dec 15 #Javascript
js修改地址栏URL参数解决url参数问题
Dec 15 #Javascript
jquery插件如何使用 jQuery操作Cookie插件使用介绍
Dec 15 #Javascript
JavaScript中OnLoad几种使用方法
Dec 15 #Javascript
Javascript中自动切换焦点实现代码
Dec 15 #Javascript
treepanel动态加载数据实现代码
Dec 15 #Javascript
You might like
PHP实现文件上传功能实例代码
2017/05/18 PHP
关于Anemometer图形化显示MySQL慢日志的工具搭建及使用的详细介绍
2020/07/13 PHP
深入分析js中的constructor和prototype
2012/04/07 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
JavaScript Promise启示录
2014/08/12 Javascript
原生js结合html5制作小飞龙的简易跳球
2015/03/30 Javascript
JavaScript学习笔记之数组随机排序
2016/03/23 Javascript
原生JS实现风箱式demo,并封装了一个运动框架(实例代码)
2016/07/22 Javascript
浅谈jQuery this和$(this)的区别及获取$(this)子元素对象的方法
2016/11/29 Javascript
JS基于正则截取替换特定字符之间字符串操作示例
2017/02/03 Javascript
Angularjs 实现移动端在线测评效果(推荐)
2017/04/05 Javascript
vue中axios处理http发送请求的示例(Post和get)
2017/10/13 Javascript
在Mac下彻底卸载node和npm的方法
2018/05/16 Javascript
layer 刷新某个页面的实现方法
2019/09/05 Javascript
vue监听dom大小改变案例
2020/07/29 Javascript
微信小程序抽奖组件的使用步骤
2021/01/11 Javascript
[01:00:22]DOTA2-DPC中国联赛定级赛 LBZS vs Magma BO3第三场 1月10日
2021/03/11 DOTA
[03:02]2020完美世界城市挑战赛(秋季赛)总决赛回顾
2021/03/11 DOTA
Django的session中对于用户验证的支持
2015/07/23 Python
Python基础语法(Python基础知识点)
2016/02/28 Python
Python写的一个定时重跑获取数据库数据
2016/12/28 Python
python3 中文乱码与默认编码格式设定方法
2018/10/31 Python
如何通过Python3和ssl实现加密通信功能
2020/05/09 Python
Python使用itcaht库实现微信自动收发消息功能
2020/07/13 Python
Python连接mysql方法及常用参数
2020/09/01 Python
海飞丝广告词
2014/03/20 职场文书
电气工程及其自动化专业毕业生自荐信
2014/06/21 职场文书
欢迎领导检查标语
2014/06/27 职场文书
模具设计与制造专业求职信
2014/07/19 职场文书
护理见习报告范文
2014/11/03 职场文书
教师节慰问信
2015/02/15 职场文书
律师函格式范本
2015/05/27 职场文书
mysql优化之query_cache_limit参数说明
2021/07/01 MySQL
Nginx缓存设置案例详解
2021/09/15 Servers
MySQL创建管理子分区
2022/04/13 MySQL