ExtJS5擁有許許多多的類(lèi),到目前為止使用ExtJS開(kāi)發(fā)的人員有200多萬(wàn),他們來(lái)自不同的地域,擁有不同的背景。所以這樣說(shuō)來(lái),在如下這些代碼結(jié)構(gòu)上提供一份公共代碼結(jié)構(gòu)上我們就面臨著一個(gè)巨大的挑戰(zhàn):
1.大家都了解和熟悉,并且簡(jiǎn)單和容易學(xué)習(xí)
2.開(kāi)發(fā)迅速,調(diào)試方便,部署的時(shí)候也沒(méi)有痛苦
3.組織性強(qiáng),可擴(kuò)展性強(qiáng),可維護(hù)性強(qiáng)
JavaScript是面向原型類(lèi)的語(yǔ)言,其最強(qiáng)大的特性就是自由,解決不同的問(wèn)題可以有好多的解決方案,并且可以使用不同的編碼風(fēng)格和技術(shù),代價(jià)就是這樣就會(huì)有很多不確定性發(fā)生。如果缺乏一個(gè)統(tǒng)一的結(jié)構(gòu),javascript代碼就很難理解、難維護(hù)和復(fù)用。
另一方面,基于類(lèi)的編程仍然是最流行的面向?qū)ο蟮木幊棠J?,基于?lèi)的語(yǔ)言通常需要強(qiáng)類(lèi)型,封裝和標(biāo)準(zhǔn)的編碼慣例,通過(guò)讓開(kāi)發(fā)人員堅(jiān)持大量的規(guī)則,讓代碼更具有可預(yù)測(cè)性,可擴(kuò)展和可伸縮性。然而,這樣就損失了JavaScript的動(dòng)態(tài)特性。
每個(gè)方法都有優(yōu)點(diǎn)和缺點(diǎn),那我們是否可以保持好的而同時(shí)隱藏壞的部分?答案是肯定的,ExtJS就是這樣一個(gè)解決方案。
命名約定
在代碼中對(duì)名稱(chēng)進(jìn)行統(tǒng)一規(guī)約,如基礎(chǔ)類(lèi)、名稱(chēng)空間和文件名,可以讓你的代碼在結(jié)構(gòu)化和可讀性上更方便組織管理。
類(lèi)命名約定
類(lèi)名只能包含字母數(shù)字字符。數(shù)字被允許但是不被鼓勵(lì),除非他們屬于一個(gè)技術(shù)術(shù)語(yǔ)。不要使用下劃線、連字符或其他任何非字母數(shù)字字符。例如: MyCompany.useful_util.Debug_Toolbar 帶有下劃線,所以不是合法的,MyCompany.util.Base64是可以的。
類(lèi)名應(yīng)該以適當(dāng)?shù)拿Q(chēng)空間,并且以對(duì)象屬性(.)進(jìn)行分組歸類(lèi)。類(lèi)名至少應(yīng)該有一個(gè)獨(dú)特的頂級(jí)名稱(chēng)空間中緊隨其后。例如:MyCompany.data.CoolProxy? MyCompany.Application
頂級(jí)名稱(chēng)空間和實(shí)際的類(lèi)名應(yīng)該采取駝峰模式,其它的則應(yīng)該都小寫(xiě),例如: MyCompany.form.action.AutoLoad
不是sencha生成的類(lèi)盡量不要使用Ext作為頂級(jí)空間??s略詞也應(yīng)該遵守駝峰預(yù)約定,如:
使用Ext.data.JsonProxy 而不是Ext.data.JSONProxy
使用 MyCompany.util.HtmlParser 而不是MyCompary.parser.HTMLParser
使用MyCompany.server.Http 而不是MyCompany.server.HTTP
源文件命名約定
類(lèi)的名稱(chēng)直接映射到它們存儲(chǔ)的文件路徑。因此,必須只有一個(gè)類(lèi)文件。例如:
Ext.util.Observable 是在如下目錄存儲(chǔ)的path/to/src/Ext/util/Observable.js
Ext.form.action.Submit 是在如下目錄存儲(chǔ)的path/to/src/Ext/form/action/Submit.js
MyCompany.chart.axis.Numeric是在如下目錄存儲(chǔ)的path/to/src/MyCompany/chart/axis/Numeric.js
path/to/src源碼路徑 是你的應(yīng)用程序類(lèi)的目錄,所有類(lèi)都應(yīng)該在本根目錄下,并且為了方便開(kāi)發(fā)、維護(hù)和部署體驗(yàn),都應(yīng)該進(jìn)行適當(dāng)?shù)拿?guī)約。
方法和變量的命名規(guī)則
以類(lèi)似類(lèi)名的方式,方法名和變量名只能包含字母,數(shù)字被允許但是不被鼓勵(lì)使用,除非他們屬于一個(gè)技術(shù)術(shù)語(yǔ)。不要使用下劃線、連字符或其他任何非字母數(shù)字字符。方法和變量名應(yīng)該遵循駝峰原則這也適用于縮略詞。
例如:
可接受的方法名稱(chēng):
encodeUsingMd5()
getHtml()而不是getHTML()
getJsonResponse()而不是getJsonResponse()
parseXmlContent()而不是parseXMLContent()
可接受的變量名:
varisGoodName
varbase64Encoder
varxmlReader
varhttpServer
屬性的命名規(guī)則
類(lèi)屬性名遵循完全相同的約定,但靜態(tài)常量除外。靜態(tài)類(lèi)常量屬性應(yīng)該全部大寫(xiě)。例如:
Ext.MessageBox.YES= "Yes"
Ext.MessageBox.NO = "No"
MyCompany.alien.Math.PI = "4.13"
聲明
你可能使用一個(gè)方法就可以完成一個(gè)類(lèi)的聲明:Ext.define。它最基本的語(yǔ)法就如:Ext.define(className,members, onClassCreated);
className:類(lèi)名
members:一個(gè)對(duì)象,代表一個(gè)類(lèi)成員的鍵-值對(duì)的集合
onClassCreated:一個(gè)可選的回調(diào)函數(shù)當(dāng),當(dāng)它所依賴(lài)的類(lèi)和類(lèi)本身創(chuàng)建完成時(shí)被調(diào)用。由于類(lèi)創(chuàng)建的異步本性,這個(gè)回調(diào)在很多情況下是非常有用的,這些將在第四部分進(jìn)一步討論。
例子:
Ext.define('My.sample.Person',{//注釋? 使用Ext.define進(jìn)行類(lèi)的定義? 定義類(lèi)名為Person 存儲(chǔ)在My/sample文件夾下
??? name: 'Unknown',
??? constructor: function(name) {//構(gòu)造函數(shù)
??????? if (name) {
??????????? this.name = name;
??????? }
??? },
??? eat: function(foodType) {//對(duì)象方法
??????? alert(this.name + " is eating:" + foodType);
??? }
});
//創(chuàng)建和使用的例子
varbob = Ext.create('My.sample.Person', 'Bob');
bob.eat("Salad");// alert("Bob is eating: Salad");
注意:我們創(chuàng)建了一個(gè)新的My.sample的實(shí)例時(shí)使用了Ext.create()方法,我們也可以使用新的關(guān)鍵字new(new
My.sample.Person())。不過(guò)建議要養(yǎng)成總是使用Ext.create的習(xí)慣,因?yàn)檫@樣您就開(kāi)啟了動(dòng)態(tài)加載,動(dòng)態(tài)加載的更多信息參見(jiàn)入門(mén)指南,動(dòng)態(tài)加載可以節(jié)省對(duì)象創(chuàng)建,提升效率節(jié)省空間。
配置
同樣,也有一個(gè)專(zhuān)用的屬性會(huì)在強(qiáng)大的Ext類(lèi)創(chuàng)建之前進(jìn)行預(yù)處理:config,它包含如下特性:
1.與其他類(lèi)成員配置是完全隔離的
2.如果getter和setter方法還未顯示定義,原生類(lèi)會(huì)在創(chuàng)建期間為每個(gè)對(duì)象屬性自動(dòng)生成。
3.自動(dòng)生成的setter方法會(huì)內(nèi)部調(diào)用apply方法(如果類(lèi)中有定義)。如果你需要運(yùn)行自定義邏輯來(lái)處理預(yù)先設(shè)置的值,你可以覆寫(xiě)apply方法申請(qǐng)配置屬性,。如果apply不返回一個(gè)值,setter不會(huì)設(shè)置值。當(dāng)不同的值被設(shè)置時(shí)update更新方法也會(huì)被調(diào)用,apply和update方法有old
value和new value作為參數(shù)。
對(duì)使用Ext configs的類(lèi),不再需要手動(dòng)調(diào)用initConfig()。但是,對(duì)于擴(kuò)展于Ext.Base的自己的類(lèi),
initConfig()方法仍然需要手動(dòng)調(diào)用。
可以看到下面的配置示例:
Ext.define('My.own.Window', {
??extend: 'Ext.Component',
??/** @readonly */
??isWindow: true,
??config: {
??????title: 'Title Here',
??????bottomBar: {
?????????? height: 50,
?????????? resizable: false
??????}
??},
??applyTitle: function(title) {
??????if (!Ext.isString(title) || title.length === 0) {
?????????? alert('Error: Title must be a validnon-empty string');
??????}
??????else {
?????????? return title;
??????}
??},
??applyBottomBar: function(bottomBar) {
??????if (bottomBar) {
??????????if (!this.bottomBar) {
?????????????? returnExt.create('My.own.WindowBottomBar', bottomBar);
?????????? }
?????????? else {
??????????????this.bottomBar.setConfig(bottomBar);
?????????? }
??????}
??}
});
/** A child component to complete the example.*/
Ext.define('My.own.WindowBottomBar', {
??config: {
??????height: undefined,
??????resizable: true
??}
});
下面是一個(gè)如何使用它的例子:
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 });
alert(myWindow.getBottomBar().getHeight());// alerts 100
靜態(tài)變量
靜態(tài)變量可以使用statics配置來(lái)定義:
Ext.define('Computer', {
???statics: {
???????instanceCount: 0,
???????factory: function(brand) {
??????????? // 'this' in static methods referto the class itself
??????????? return new this({brand: brand});
???????}
???},
???config: {
???????brand: null
???}
});
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"
錯(cuò)誤控制和調(diào)試
Ext JS包括一些有用的特性,將幫助您調(diào)試和錯(cuò)誤處理。
您可以使用Ext.getDisplayName()來(lái)獲取任何方法的顯示名稱(chēng)。這對(duì)拋出錯(cuò)誤的類(lèi)名和方法名描述來(lái)說(shuō)是特別有用的:
throw new Error('['+Ext.getDisplayName(arguments.callee) +'] Some message here');
當(dāng)有錯(cuò)誤在使用Ext.define時(shí)拋出的時(shí)候,你應(yīng)該查看這個(gè)方法還有類(lèi)的堆棧信息,你可以看下谷歌Chrome中報(bào)錯(cuò)的信息如下:
