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 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
Mar 10 Javascript
js异或加解密效果代码
Jun 25 Javascript
javascript 用记忆函数快速计算递归函数
Mar 15 Javascript
jQuery帮助之筛选查找 children([expr])
Jan 31 Javascript
js交换排序 冒泡排序算法(Javascript版)
Oct 04 Javascript
javascript去除字符串左右两端的空格
Feb 05 Javascript
javascript将中国数字格式转换成欧式数字格式的简单实例
Aug 02 Javascript
快速实现jQuery多级菜单效果
Feb 01 Javascript
实例详解JSON取值(key是中文或者数字)方式
Aug 24 Javascript
基于VUE实现的九宫格抽奖功能
Sep 30 Javascript
angular6根据environments配置文件更改开发所需要的环境的方法
Mar 06 Javascript
JS判断数组里是否有重复元素的方法小结
May 21 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
MySQL数据库转移,access,sql server 转 MySQL 的图文教程
2007/09/02 PHP
php木马webshell扫描器代码
2012/01/25 PHP
php 读取文件头判断文件类型的实现代码
2013/08/05 PHP
分享50个提高PHP执行效率的技巧
2015/12/26 PHP
CI框架常用方法小结
2016/05/17 PHP
Laravel框架集合用法实例浅析
2020/05/14 PHP
自动完成JS类(纯JS, Ajax模式)
2009/03/12 Javascript
JavaScript 无符号右移运算符
2009/04/17 Javascript
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
JS实现图片放大镜效果的方法
2015/02/27 Javascript
基于AngularJS实现页面滚动到底自动加载数据的功能
2015/10/16 Javascript
JS基于VML技术实现的五角星礼花效果代码
2015/10/26 Javascript
jQuery解决input元素的blur事件和其他非表单元素的click事件冲突问题
2016/08/15 Javascript
jQuery右下角悬浮广告实例
2016/10/17 Javascript
获取select的value、text值的简单示例(jquery与javascript)
2016/12/07 Javascript
javascript数据类型详解
2017/02/07 Javascript
vue使用watch 观察路由变化,重新获取内容
2017/03/08 Javascript
jquery ztree实现右键收藏功能
2017/11/20 jQuery
vue中锚点的三种方法
2018/07/06 Javascript
你应该了解的JavaScript Array.map()五种用途小结
2018/11/14 Javascript
python 实现文件的递归拷贝实现代码
2012/08/02 Python
用Python编写一个每天都在系统下新建一个文件夹的脚本
2015/05/04 Python
python导入时小括号大作用
2017/01/10 Python
Django实现简单分页功能的方法详解
2017/12/05 Python
pycharm 配置远程解释器的方法
2018/10/28 Python
利用Django模版生成树状结构实例代码
2019/05/19 Python
Keras-多输入多输出实例(多任务)
2020/06/22 Python
python实现文件+参数发送request的实例代码
2021/01/05 Python
e路東瀛(JAPANiCAN)香港:日本旅游、日本酒店和温泉旅馆预订
2018/11/21 全球购物
外贸英语专业求职信范文
2013/12/25 职场文书
管理岗位竞聘演讲稿
2014/08/18 职场文书
安全环保演讲稿
2014/08/28 职场文书
golang import自定义包方式
2021/04/29 Golang
Django中的JWT身份验证的实现
2021/05/07 Python
SpringBoot中获取profile的方法详解
2022/04/08 Java/Android
CSS SandBox应用场景及常见问题
2022/06/25 HTML / CSS