ExtJS 4的類系統(class system)進行了一次重大重構,ExtJS4的新架構就是基於這套新的類系統構建的,所以有必要先了解如下這個class system
這篇文章分爲四章 chrome
ExtJS 4 有300多個類,社區裏有20w+不一樣背景的開發者,提供一個好的代碼架構是個巨大的挑戰: 編程
JavaScript是個基於原型鏈繼承的語言,沒有類的概念。並且JavaScript語言特色就是鬆散和自由,實現一個一樣的功能,能夠有不少種方式,可是若是聽任它的鬆散和自由,就很難維護和重用代碼。
面向對象編程絕大部分都是基於類的。基於類的編程語言一般須要強類型,提供代碼封裝,而且有標準的編碼習慣,說了一堆廢話,不翻譯了,總結如下就是能作到既有面向對象編程的規範性,又能作到JavaScript的靈活性 架構
命名規範,使用一致的命名規範可讓你的代碼結構清晰,可讀性強。 app
類名只能包含字母數字,不推薦使用數字,除非是經常使用詞。不要用下劃線中化纖等非字母數字字符。 異步
類應該組織在包或者說命名空間下面,而且至少要有一個頂層命名空間,例如:編程語言
MyCompany.data.CoolProxy MyCompany.Application
頂層命名空間和真正的類,應該採用駝峯式命名,其餘一概小寫,例如:函數
MyCompany.form.action.AutoLoad
非Ext官方類,不能夠在Ext頂層命名空間下(這是爲了防止衝突)
首字母組合詞也要採用駝峯式命名,例如: 學習
類的命名和源文件存放路徑是對應的,例如: this
path/to/src/Ext/util/Observable.js
path/to/src/Ext/form/action/Submit.js
path/to/src/MyCompany/chart/axis/Numeric.js
這裏面的path/to/src
就是程序跟目錄下的那個app目錄,全部類都應該這樣組織,保證維護性 編碼
例如:
encodeUsingMd5()
,getHtml()
代替getHTML()
,getJsonResponse()
代替getJSONResponse()
,parseXmlContent()
代替parseXMLContent()
var isGoodName;
, var base64Encoder
, var xmlReader
, var httpServer
Ext.MessageBox.YES = "Yes" Ext.MessageBox.NO = "No" MyCompany.alien.Math.PI = "4.13"
若是你使用過ExtJS 3或者以前的版本,可能會熟悉Ext.extend,能夠用來建立一個類
1
var MyWindow = Ext.extend(Object, { ... });
這個方法很容易就能夠聲明一個類並繼承自另外一個類,可是也有缺陷
1
My.cool.Window = Ext.extend(Ext.Window, { ... });
這個例子中咱們須要把類定義在命名空間裏,並繼承自Ext.Window類,可是有兩個問題:
My.cool
必須以前定義過,這個命名空間必須已經存在 Ext.Window
必須已經加載第一條一般可使用Ext.namespace
(同Ext.ns
)解決,這個方法會把不存在的命名空間都建立出來,無聊的是你必須記得在Ext.extend
以前加上這句話
Ext.ns('My.cool'); My.cool.Window = Ext.extend(Ext.Window, { ... });
第二個問題,ExtJS4之前的版本都很差解決依賴問題,所以一般是引入ext-all.js
ExtJS 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");
注意這裏建立一個新的My.sample.Person
實例使用的是Ext.create()
方法,使用new
關鍵字也能夠建立實例(new My.sample.Person()
),可是不推薦使用new
,應該養成使用Ext.create
的習慣,由於這樣能夠利用到動態加載的好處,有關動態加載能夠參看個人另一篇教程 ExtJS 4 入門
ExtJS 4 中引入了一個專用的config
屬性,這個屬性在類建立以前,會被Ext.Class
預先處理,並有一下特性:
apply
方法,apply
方法在setter以前調用,能夠經過apply
方法定製setter的行爲,若是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
靜態成員經過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"
ExtJS 4 引入了不少有用的特性幫助調試和錯誤處理
可使用Ext.getDisplayName()
得到函數名稱,例如
1
throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');
在用Ext.define()
定義出來的類中拋出(throw)錯誤(error),能夠在safari或者chrome的控制檯中看到方法名和類名和調用棧