EXTJS4官方文檔翻譯系列一:類系統和編碼規范,轉載自《學而知不足》的技術博客,原文如下:
上個禮拜開始使用extjs4,之前都沒用過ext,所以現在只好努力的看文檔了,順便記下來避免以后忘記.括號中內容是我自己添加的備注或者原文.英語比較爛,但不想一直爛,所以試著翻譯,希望大家指能出錯誤的地方,英語好的建議看官方文檔,不要被我誤導了.
地址: http://docs.sencha.com/ext-js/4-0/#/guide/class_system
PS:上次說要翻譯的一些titanium的文檔,無奈后面太監了..沒辦法,工作用不上,業余時間要學工作的東西.titanium雖然喜歡,但是很久沒去碰了.有機會繼續吧..
ext4使用新的類機制進行了大量的重構,這在ext的歷史上還是第一次!為了支撐新的架構,ext4幾乎重寫了每一個類,因此最好先好好的理解一下新的架構,再開始編碼
本文適合想在extjs4中擴展現有類或者創建新類的開發者(注:其實想用ext4的都要看看).共分為4個部分:
第一部分:概述,說明了強大的類機制的必要性.
第二部分:編碼規范,討論類、方法、屬性、變量和文件命名的最佳實踐.
第三部分:動手,詳細的編碼示例.
第四部分:錯誤處理和調試,提供一些有用的調試和異常處理技巧
一,概述
ExtJS4擁有超過300個的類.迄今為止,我們的社區擁有超過20萬來自世界各地,使用不同后臺語言的開發者.要在這種規模的框架上提供具有以下特點的架構,需要面臨巨大的挑戰:
1,簡單易學。2,快速開發、調試簡單、部署容易。3,良好的結構、可擴展性和可維護性。
javascript是一種類無關(原文:classless)、基于原型的語言。因此javascript最強大的特點是靈活。同樣的事情可以使用不同的方式,不同的編碼風格和技巧去完成。這個特點也會帶來一些不可預測的風險。如果沒有統一的編碼規范,javascript代碼將很難理解、維護和復用。
相反的,基于類的編程語言擁有較為流行的面向對象模型,強類型、內建的封裝機制和強制的編碼約束等特點。通過強制開發人員遵守一些大的原則來使代碼的行為更容易被理解,以及提高可擴展性(這里不明白,javascript這類動態語言不是更容易擴展么?)和可伸縮性。但是,這類語言沒有javascript的靈活性。
二,命名約定
在所有類、命名空間(namespace)和文件名中使用一致的命名約定,有助于保持代碼的良好結構和可讀性。
1)類
類名只能包含字母和數字。允許包含數字,但是大部分情況下不建議使用,除非這些數字是專業術語的一部分。不要使用下劃線,連字符等非數字字母符號。例如:
MyCompany.useful_util.Debug_Toolbar 不建議
MyCompany.util.Base64 合適的(雖然包含數字,但是數字是術語的一部分)
類名應該包含在使用點號分隔的命名空間中。至少,要有一個頂級命名空間。例如:
MyCompany.data.CoolProxyMyComp
MyCompany.data.CoolProxyMyCompa
頂級命名空間和實際的類名應使用駝峰命名(CamelCased),其他則為小寫。例如:
MyCompany.form.action.AutoLoad
不是Sencha開發的類(即不是Ext自帶的)不要使用Ext做為頂級命名空間。
縮寫也要遵守以上的駝峰式命名約定。例如:
Ext.data.JsonProxy而不是Ext.data.JSONProxy MyCompany.util.HtmlParser而不是MyCompary.parser.HTMLParser MyCompany.server.Http而不是MyCompany.server.HTTP
2)代碼文件
類名對應類所在的文件(包括文件名)。因此,每個文件應該只包含一個類(類名和文件名一樣)。例如:
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 是你應用程序所在目錄。所有類都應該在這個通用根目錄下,并且使用適當的命名空間以利于開發、維護和部署。
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) 舊的方式
如果你曾經使用過舊版本的extjs,那么你肯定熟悉使用Ext.extend來創建一個類:
1: varMyWindow=Ext.extend(Object,{...});
這個方法很容易從現有的類中繼承創建新的類.相比直接繼承,我們沒有好用的API用于類創建的其他方面,諸如:配置、靜態方法、混入(Mixins)。呆會我們再來詳細的重新審視這些方面?,F在,讓我們來看看另一個例子:
1: My.cool.Window = Ext.extend(Ext.Window, { ... });
在這個例子中,我們創建我們的新類,繼承Ext.Window,放在命名空間中。我們有兩個問題要解決:
1,在我們訪問My.cool的Window屬性之前,My.cool必須是一個已有的對象.
2,Ext.Window必須在引用之前加載.
第一個問題通常使用Ext.namespace(別名Ext.ns)來解決.該方法遞歸創建(如果該對象不存在)這些對象依賴.比較繁瑣枯燥的部分是你必須在Ext.extend之前執行Ext.ns來創建它們.
1: Ext.ns('My.cool');
2: My.cool.Window = Ext.extend(Ext.Window, { ... });
第二個問題不好解決,因為Ext.Window可能直接或間接的依賴于許多其他的類,依賴的類可能還依賴其它類...出于這個原因,在ext4之前,我們通常引入整個ext-all.js,即使是我們只需要其中的一小部分.
1.2) 新的方式
在Extjs4中,你只需要使用一個方法就可以解決這些問題:Ext.define.以下是它的基本語法:
1: Ext.define(className, members, onClassCreated);
onClassCreated: 可選的回調函數,在所有依賴都加載完畢,并且類本身建立后觸發.由于類創建的新的異步特性,這個回調函數在很多情況下都很有用.這些在第四節中將進一步討論
例如:
1: Ext.define('My.sample.Person', {
2: name: 'Unknown',
3:
4: constructor: function(name) {
5: if (name) {
6: this.name = name;
7: }
8:
9: return this;
10: },
11:
12: eat: function(foodType) {
13: alert(this.name + " is eating: " + foodType);
14:
15: return this;
16: }
17: });
18:
19: var aaron = Ext.create('My.sample.Person', 'Aaron');
20: aaron.eat("Salad"); // alert("Aaron is eating: Salad");
注意我們使用Ext.create()方法創建了My.sample.Person類的一個新實例.我們也可以使用新的關鍵字(new My.sample.Person())來創建.然而,建議養成始終用Ext.create來創建類示例的習慣,因為它允許你利用動態加載的優勢.更多關于動態加載信息,請看入門指南:入門指南
2).配置
在ExtJS 4 ,我們引入了一個專門的配置屬性,用于提供在類創建前的預處理功能.特性包括:
1: Ext.define('My.own.Window', {
2: /** @readonly */
3: isWindow: true,
4:
5: config: {
6: title: 'Title Here',
7:
8: bottomBar: {
9: enabled: true,
10: height: 50,
11: resizable: false
12: }
13: },
14:
15: constructor: function(config) {
16: this.initConfig(config);
17:
18: return this;
19: },
20:
21: applyTitle: function(title) {
22: if (!Ext.isString(title) || title.length === 0) {
23: alert('Error: Title must be a valid non-empty string');
24: }
25: else {
26: return title;
27: }
28: },
29:
30: applyBottomBar: function(bottomBar) {
31: if (bottomBar && bottomBar.enabled) {
32: if (!this.bottomBar) {
33: return Ext.create('My.own.WindowBottomBar', bottomBar);
34: }
35: else {
36: this.bottomBar.setConfig(bottomBar);
37: }
38: }
39: }
40: });
以下是它的用法:
1: var myWindow = Ext.create('My.own.Window', {
2: title: 'Hello World',
3: bottomBar: {
4: height: 60
5: }
6: });
7:
8: alert(myWindow.getTitle()); // alerts "Hello World"
9:
10: myWindow.setTitle('Something New');
11:
12: alert(myWindow.getTitle()); // alerts "Something New"
13:
14: myWindow.setTitle(null); // alerts "Error: Title must be a valid non-empty string"
15:
16: myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100
3.Statics
靜態成員可以使用statics配置項來定義
1: Ext.define('Computer', {
2: statics: {
3: instanceCount: 0,
4: factory: function(brand) {
5: // 'this' in static methods refer to the class itself
6: return new this({brand: brand});
7: }
8: },
9:
10: config: {
11: brand: null
12: },
13:
14: constructor: function(config) {
15: this.initConfig(config);
16:
17: // the 'self' property of an instance refers to its class
18: this.self.instanceCount ++;
19:
20: return this;
21: }
22: });
23:
24: var dellComputer = Computer.factory('Dell');
25: var appleComputer = Computer.factory('Mac');
26:
27: alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts "Mac"
28:
29: alert(Computer.instanceCount); // Alerts "2"
四.錯誤處理&調試
Extjs 4包含一些有用的特性用于調試和錯誤處理.
1: throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');
當使用Ext.define()定義的類中的方法拋出異常后.你將在調用堆棧中看到類和方法名(如果你使用webkit).例如,以下是chrome瀏覽器的效果: