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 相关文章推荐
IE6下通过a标签点击切换图片的问题
Nov 14 Javascript
jquery获取子节点和父节点的示例代码
Sep 10 Javascript
jQuery知识点整理
Jan 30 Javascript
JSON与XML优缺点对比分析
Jul 17 Javascript
javascript数据结构之双链表插入排序实例详解
Nov 25 Javascript
利用BootStrap弹出二级对话框的简单实现方法
Sep 21 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
Nov 17 Javascript
vue双向绑定的简单实现
Dec 22 Javascript
干货!教大家如何选择Vue和React
Mar 13 Javascript
vue数据控制视图源码解析
Mar 28 Javascript
Vue项目中跨域问题解决方案
Jun 05 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
Oct 24 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无敌近乎加密方式!
2010/07/17 PHP
PHP中数组合并的两种方法及区别介绍
2012/09/14 PHP
php把数据表导出为Excel表的最简单、最快的方法(不用插件)
2014/05/10 PHP
9条PHP编程小知识及易犯的小错误
2015/01/22 PHP
js类型检查实现代码
2010/10/29 Javascript
jquery下为Event handler传递动态参数的代码
2011/01/06 Javascript
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
node.js实现多图片上传实例
2014/06/03 Javascript
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
2014/09/26 NodeJs
javascript工厂方式定义对象
2014/12/26 Javascript
jQuery简单实现禁用右键菜单
2015/03/10 Javascript
jQuery绑定自定义事件的魔法升级版
2016/06/30 Javascript
js实现右键自定义菜单
2016/12/03 Javascript
Angular2下使用pdf插件的方法详解
2017/04/29 Javascript
JS请求servlet功能示例
2017/06/01 Javascript
jquery+css实现下拉列表功能
2017/09/03 jQuery
快速解决vue-cli在ie9+中无效的问题
2018/09/04 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
Vue全局loading及错误提示的思路与实现
2019/08/09 Javascript
解决layer图标icon不加载的问题
2019/09/04 Javascript
JS页面动态绘图工具SVG,Canvas,VML介简介
2020/10/16 Javascript
在vue中使用jsonp进行跨域请求接口操作
2020/10/29 Javascript
vue 函数调用加括号与不加括号的区别
2020/10/29 Javascript
[01:57]2018年度DOTA2最具潜力解说-完美盛典
2018/12/16 DOTA
[20:39]DOTA2-DPC中国联赛 正赛开幕式 1月18日
2021/03/11 DOTA
python魔法方法-属性访问控制详解
2016/07/25 Python
使用pip安装python库的多种方式
2019/07/31 Python
python 动态绘制爱心的示例
2020/09/27 Python
Internet主要有哪些网络群组成
2015/12/24 面试题
中科软测试工程师面试题
2012/06/16 面试题
社会调查研究计划书
2014/05/01 职场文书
2015学生会文艺部工作总结
2015/04/03 职场文书
初一年级组工作总结
2015/08/12 职场文书
党员心得体会范文2016
2016/01/23 职场文书
街道办残联2016年助残日活动总结
2016/04/01 职场文书
利用Python实现模拟登录知乎
2022/05/25 Python