ST2 采用跟Ext JS 4一样的类系统。这使得我们可以很轻松地在JavaScript中创建或继承新的类。类系统提供了继承,依赖加载,mixin,强大的配置选项等内容。
简单来说,类是一个拥有一些属性和方法的对象。例如:定义一个动物类,定义其名称和功能,使得它能说话,我们只需这样做:
1
2
3
4
5
6
7
8
9
|
Ext.define(
'Animal'
, {
config: {
name:
null
},
speak:
function
() {
alert(
'grunt'
);
}
});
|
这样我们就定义了一个动物类,每个动物可以有一个名称,并可以说话。要创建一个新的的动物,我们只需这样:
1
2
3
4
|
var
bob = Ext.create(
'Animal'
, {
name:
'Bob'
});
bob.speak();
//alerts 'grunt'
|
在这里,我们创建了一个名为Bob的动物,并命令它说话。现在,我们已经定义了一个类和并创建了一个实例,但我们不知道鲍勃是什么物种,所以让我们定义一个人类的作为动物类的子类:
1
2
3
4
5
6
7
|
Ext.define(
'Human'
, {
extend:
'Animal'
,
speak:
function
() {
alert(
this
.getName());
}
});
|
现在我们已经从动物类继承了一个新的的人类,因此人类获得其所有的方法和配置。实际上,我们重写了说话的方法,因为大多数人有足够的智慧,说他们的名字,而不是咕噜咕噜地叫。现在,我们创建一个名为Bob的人,并让他说话:
1
2
3
4
5
|
var
bob = Ext.create(
'Human'
, {
name:
'Bob'
});
bob.speak();
//alerts 'Bob'
|
你应该也注意到了上面的代码中使用了getName方法,然而我们并没有定义动物类的getName方法。那它来自哪里?答案是:框架自动帮每一个配置项添加了以下方法:
- 一个getter方法 - 如getName就是返回name的当前值。
- 一个setter方法 - 如getName就是为name设置一个新值。
- an applier function - applyName() in this case - which is called by the setter and lets you run a function when a configuration changes
getter和setter都是自动生成的,建议大家使用它们来存取类里面的数据。ST的每一个组件都使用了getter和setter的模式,这意味着如果我们知道一个配置项,也就知道如何获取和设置它的值了。
这也让你的的代码更整洁。举个例子:如果你想在改变Bob的名字时询问用户。就可以定义applyName方法,它会被自动调用:
1
2
3
4
5
6
7
|
Ext.define(
'Human'
, {
extend:
'Animal'
,
applyName:
function
(newName, oldName) {
return
confirm(
'Are you sure you want to change name to '
+ newName +
'?'
);
}
});
|
我们用浏览器内建的confirm方法弹出了一个确认操作的对话框。如果applier方法返回的是false,那name的值将不会发生改变。
1
2
3
4
5
6
7
8
9
|
var
bob = Ext.create(
'Person'
, {
name:
'Bob'
});
bob.setName(
'Fred'
);
//opens a confirm box, but we click No
bob.speak();
//still alerts 'Bob'
我们已经学习了类系统的这些内容:
|
- 用Ext.define来定义新的类。
- 用Ext.create来创建对象实例。例如:Ext.create('SomeClass', {some: 'configuration'})
- 用"extend"来继承扩展类。
- 使用系统自动生成的getter和setter方法,这会让代码更整洁。
现在,你已经学会如何定义和使用一个类。但类系统的内容远远不只这些。
依赖与动态加载
大多数时候,类之间都存在着依赖。我们可以使用"requires"关键字来引入一个被依赖的类。人类依赖动物类并扩展动物类,这种情况下并不需要特殊的说明,用"extend"就已经表明了这种依赖关系。
1
2
3
4
5
6
7
8
9
|
Ext.define(
'Human'
, {
extend:
'Animal'
,
requires:
'Ext.MessageBox'
,
speak:
function
() {
Ext.Msg.alert()
}
});
|
当你像这样定义一个类的时候,ST就会检查并异步加载Ext.MessageBox。
Ext.MessageBox也可能依赖于其他类,这些类也将在后台自动加载。Ext.MessageBox和动物类都加载完毕后,就会定义人类。然后就可以使用Ext.create实例化"人"了。
在开发过程中,多文件可以让我们有效地管理代码,但应用发布后,应该尽量减少文件的数目以提高网络响应速度。ST2的JSBuilder工具可以分析你的应用程序,并将你所有代码连同你所用到的ST中的类合并成一个js文件。关于JSBuilder使用方法的介绍,请看指南的第二部分。
每种方法都有其自身的利弊,我们是否能够取其精华,去其糟粕?答案是肯定的,在ST2里,我们已经实现了这一目标。
命名约定
使用统一的风格来命名类、名空间和文件名有助于更好地组织代码,保证代码的条理性和可读性。
1) 类
类名只能由字符和数字组成。不要在类名中出现数字,除非它属于一个技术术语。不要使用下划线,连字符,以及任何字母数字以外的字符。例如:
- MyCompany.useful_util.Debug_Toolbar 不要这样写
- MyCompany.util.Base64 这个OK
每个类都要有命名空间。用"."来为类分配命名空间,把类分配到不同的包内。例如:
- MyCompany.data.CoolProxy
- MyCompany.Application
顶级的命名空间和类名使用骆驼拼写法,其他的都用小写。例如:
- MyCompany.form.action.AutoLoad
非框架本身的类,不要使用Ext作为顶级命名空间。
首字母缩略词也应该遵循上面列出的骆驼拼写法约定。例如:
- 使用 Ext.data.JsonProxy 而不用 Ext.data.JSONProxy
- 使用 MyCompany.util.HtmlParser 而不用 MyCompary.parser.HTMLParser
- 使用 MyCompany.server.Http 而不用 MyCompany.server.HTTP
2) 源文件
类名直接映射到类文件的存储路径。因此,每个文件对应一个类(就像java一样)例如:
- Ext.util.Observable 存储位置为 path/to/src/Ext/util/Observable.js
- Ext.form.action.Submit 存储位置为 path/to/src/Ext/form/action/Submit.js
- MyCompany.chart.axis.Numeric 存储位置为 path/to/src/MyCompany/chart/axis/Numeric.js
其中 path/to/src 是你存储脚本的目录(译者注:这里不是真的"path/to"而是你的app目录),所有的类都应该保存在这个目录下,并被正确地划分命名空间。这样Ext .require()方法才能正确地动态载入脚本文件。这样对将来的维护和部署工作都也很会有帮助。
3) 变量和方法
- 跟类名一样, 变量名和方法名只能由字符和数字组成。不要在类名中出现数字,除非它属于一个技术术语。不要使用下划线,连字符,以及任何字母数字以外的字符。
- 变量名和方法名应该使用首字母小写的骆驼拼写法。示例:
- 好的方法名: getHtml() getJsonResponse() parseXmlContent()
- 不好的方法名:getHTML() getJSONResponse() parseXMLContent()
- 好的变量名:isGoodName base64Encoder xmlReader httpServer
4) 属性
- 除静态属性以外的类的属性,其命名方式跟方法和变量的一样。
- 静态属性全部用大写命名,例如:
- Ext.MessageBox.YES = "Yes"
- Ext.MessageBox.NO = "No"
- MyCompany.alien.Math.PI = "4.13"