在mvc結構的基礎上,sencha touch又使用了sencha公司為extjs4開發出來的類系統,在面向對象的編程語言中,類是對對象的定義,它描述了對象所包含的大量屬性和方法。
跟面向對象語言類似,sencha touch的類提供了繼承,依賴加載,mixins,屬性方法設置這些強大的功能。
sencha touch將自己封裝成了一個面向對象的開發框架,如果你去查看官方的api,你會發現在面向對象編程語言中所需要用到的大量函數sencha touch全都給你封裝出來了,你需要的大部分功能直接調用它的api就能實現,這里我們來詳細介紹sencha touch的類系統。
簡單的說,一個類就是就是對一個對象的屬性和方法的簡單定義,下面我們來演示一下如何使用st的類系統,
首先我們來定義一個動物類,它有自己的名字,並且可以執行說話這個動作:
Ext.define('Animal', { config: { name: null //動物的名字,這里默認值為null }, //構造函數 constructor: function(config) { this.initConfig(config); }, //動物說出自己的名字 speak: function() { console.log("speak方法執行結果:",'我的名字是' + this.getName()); } });
大家看到,這里我們定義了一個動物類,
在st中 ,我們使用Ext.define(“className”,{properties})來定義一個類,參數如下
“className”:定義的類的名稱;
{properties}:定義的類的屬性或方法
注意:定義類的時候類里面有個config屬性,我們給類定義的所有屬性都必需寫在config里,在config里定義的屬性會自動生成get,set,apply和update
四種方法(下面會詳細講解),在開發過程中,官方api中定義的屬性都必需寫在config下,否則會出錯或者設置無效,這點跟extjs4有些區別,
很多同學從extjs4轉過來后習慣性的將屬性寫在config外,結果代碼效果始終不對,所以這點必須要注意
同時在config中定義的屬性是位於js對象的原型propertype中的,所以用js對象.屬性的方法是取不到的,我們后面會講如何來取屬性的值
接下來我們來實例化這個類,並調用它的speak方法
var mine = Ext.create('Animal', { name: '黃飛鴻', test: '呵呵' }); mine.speak();//輸出我的名字是黃飛鴻 console.log(mine.getName());//輸出黃飛鴻
上面的代碼中,我們通過Ext.create實例化了Animal這個類,並且將它賦值給了mine變量,我們講解下整個過程
首先,在st中,我們都是使用Ext.create("className",{properties})來實例化類的,其中的參數如下:
"className":對應你要實例化的類的名稱,即你創建類時define的類名,
{properties}:是可選的,你可以通過這個參數配置來動態設置你的類的屬性或者方法,
當我在create的時候傳入了name:"黃飛鴻"這個屬性時,如果類的config中屬性定義中有這個屬性
這個name會在對象的實例中創建一個_name屬性來存儲這個值,這時我們可以通過st類系統自動為屬性生成的get方法來獲取name屬性的值
mine.getName()//推薦用法
或者使用
mine._name//不推薦使用,只讓大家了解下原理
我們上面的定義還傳入了一個test:"呵呵"屬性,由於我們在定義對象時並沒有定義這個屬性,所以在對象實例化的時候它並不會向name那樣生成一個_name屬性,
如果要獲取它的值我們只有通過
mine.config.test
來獲取,其他方式都獲取不到test的值,所以一般情況下,如果你要自定義屬性,建議在定義類的時候將屬性先定義好,
類中的方法的調用我們直接使用類.方法名()就可以了,
接下來我們通過代碼演示來讓大家更直觀的認識下st的類的定義跟創建
為了方便查看,我們把這段代碼寫到MyFirst項目中的app.js中的launch里,如下:
launch: function() { // 銷毀啟動動畫,項目啟動時的那三個閃爍點,可根據情況需要進行修改 Ext.fly('appLoadingIndicator').destroy(); Ext.define('Animal', { config: { name: null //動物的名字 }, //構造函數 constructor: function(config) { this.initConfig(config); }, //動物說話的動作 speak: function() { console.log("speak方法執行結果:",'我的名字是' + this.getName()); } }); var mine = Ext.create('Animal', { name: '黃飛鴻', test: "呵呵" }); mine.name = "test"; mine.speak(); console.log("mine的對象結構",mine); console.log("標准寫法:",mine.getName()); console.log("演示寫法:",mine._name);
console.log("test屬性獲取:",mine.config.test); },
這時我們訪問本地地址http://127.0.0.1/MyFirst/來查看下結果,上面的代碼內容我都通過console指令來進行的輸出,至於console指令大家可以百度自己學習下,功能很強大,
項目運行起來,我們觀察下chrome的console控制台
config中屬性的講解
在上面的講解中,很多人會好奇為什么使用getName()方法能獲取到name屬性的值,它是從哪里來的呢
這是因為當我們在定義一個類的屬性時,寫入config中的屬性在實例化的時候會自動生成4個方法:
1.get方法,用來獲取屬性當前的值,例如屬性為name,則通過對象實例.getName()來獲取該屬性的值,注意get后面的首字母要大寫;
2.set方法,這個方法跟get相反,是用來給屬性賦值的,我們可以通過對象實例.setName("屬性值")來給name屬性賦值,注意set后的首字母也是大寫;
3.apply方法,這個方法會在對象的屬性值發生改變時觸發,並且會返回它最終運行的結果給對應的屬性,
4.update方法,這個方法會在apply方法被觸發后,當apply方法返回的值跟原先的屬性值不相同時觸發
下面我們用代碼簡單演示下這幾個方法,讓大家更直觀的理解上面的4個方法,將launch的代碼改為:
1 launch: function() { 2 // 銷毀啟動動畫,項目啟動時的那三個閃爍點,可根據情況需要進行修改 3 Ext.fly('appLoadingIndicator').destroy(); 4 5 Ext.define('Animal', { 6 config: { 7 name: null //動物的名字 8 }, 9 10 //構造函數 11 constructor: function(config) { 12 this.initConfig(config); 13 }, 14 15 //動物說話的動作 16 speak: function() { 17 console.log("speak方法執行結果:",'我的名字是' + this.getName()); 18 } 19 }); 20 21 //定義一個Human對象,繼承自Animal對象 22 Ext.define('Human', { 23 extend: 'Animal',//extend用來指定繼承的父類 24 25 applyName: function(newName, oldName) { 26 console.log('applyName被觸發'); 27 return confirm('你確定要修改名字為 ' + newName + '?')? newName : oldName; 28 }, 29 30 updateName: function(newName, oldName) { 31 console.log('updateName被觸發:','姓名被修改,新的名字為: ' + newName); 32 } 33 }); 34 35 //實例化一個Human對象,並設置其name屬性為'Bob' 36 var bob = Ext.create('Human', { 37 name: 'Bob' 38 }); 39 40 41 42 bob.setName('Fred'); //會觸發applyName屬性,並根據函數的執行結果返回一個值給該屬性 43 44 bob.speak(); //輸出Fred 45 },
這里我們定義了一個新的類對象Human,它繼承自Animal,Animal就是它的父類,Human對象也就繼承了Animal的name屬性跟speak方法,關於繼承的概念,這里就不多講了,網上很多教程,大家可以自己百度下。
接着我們運行項目,查看下整個代碼的運行過程,
首先當代碼執行到36行實例化對象時,
我們給對象的name屬性傳入了一個'Bob'值,這時,由於name屬性的值發生了變化
會觸發applyName方法,一般情況下applyName方法都是為空的,這里我們重寫了applyName方法;
return confirm('你確定要修改名字為 ' + newName + '?')? newName : oldName;
讓它在觸發時使用confirm方法提醒用戶屬性值發生了變化,並根據用戶的選擇是否替換新的name值,如果用戶選擇否,會返回原來的name值給name屬性,
那么這時,由於屬性的最終值跟原先並沒有發生變化,所以updateName方法就不會被觸發,
當用戶選擇確認更換時,返回新的值給屬性,由於屬性值此時發生了改變,updateName屬性就會被觸發,並在控制台輸出姓名被修改,新的名字為:xxx
大家可以自己加入代碼運行下項目觀察下控制台的輸出變化
下一講我們會對類系統進行講解