最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Extjs學(xué)習(xí)筆記之八 繼承和事件基礎(chǔ)

 更新時間:2010年01月08日 22:27:20   作者:  
只有有了事件,頁面才能真正的“活”起來。Extjs的事件也是經(jīng)過良好封裝的,對于事件的處理都由Ext.uitl.Observable類提供接口。
這里接口的意思是Observable實際上起了一個抽象類的作用,Extjs中有大量的組件都是繼承自這個類的。這個類提供了一些基本的方法比如addEvents,addlistener,fireEvent等等。

本文暫時不介紹如何使用extjs的組件響應(yīng)事件,而是介紹Extjs的事件的一些實現(xiàn)原理。整個Extjs框架都是以一種面向?qū)ο蟮姆绞介_發(fā)的,所以理解Javascript中的繼承也很重要。我前面的一篇文章 補點基礎(chǔ):Javascript中的類和閉包 也是為這篇做準(zhǔn)備。另外,博客園內(nèi)還有一個寫的很好的系列 JavaScript繼承詳解. 他主要是根據(jù)Douglas Crockford的兩篇文章寫的。 其實實現(xiàn)繼承的原理都差不多,大家可以參考閱讀。

Extjs實現(xiàn)繼承的函數(shù)是一個很核心的函數(shù)Ext.extend,extend方法有兩個重構(gòu)版本,第一個接受兩個參數(shù),第一個是extend( Function superclass, Object overrides ) ,第二個是extend( Function subclass, Function superclass,Object overrides ) : Function,第二個版本是在subclass的基礎(chǔ)上。superclass就是超類的構(gòu)造函數(shù),overrides是一個對象,里邊的屬性就是要覆蓋父類的屬性。繼承了父類的子類具有父類的prototype中的所有方法。并且子類可以覆蓋父類的方法(override),更進(jìn)一步,子類的每個對象也可以覆蓋父類的方法。其實我覺得這個函數(shù)沒什么作用,修改prototype的效果是等效的,當(dāng)然,extjs的目的肯定是要把prototype這個神奇的東西完全屏蔽起來,使程序員能夠像處理其他語言一樣來處理Javascript。當(dāng)然,即使如此,它的繼承和一般的繼承還是有些不同的,下面先看個例子,準(zhǔn)備好一個Person類
復(fù)制代碼 代碼如下:

Person = function(name) {
this.name = name;
this.fn = function() { alert('I am a person') };
}
Person.prototype.print=function(){ alert('I am a person');}
Person.prototype.showAge = function() { alert('I am older than 0'); }
Person.prototype.showName = function() { alert('Show Name:'+this.name) };
var per = new Person('Tom');
per.showName();子類:Student = function(id) {
this.id = id;
}
Student.prototype.showID = function() { alert(this.id); } //子類的方法

繼承:
Ext.extend(Student, Person);
stu.showName(); !!沒有結(jié)果!stu沒有name的定義stu.fn(); !!沒有結(jié)果 stu.showID(); !!!還是沒有結(jié)果到此我們已經(jīng)發(fā)現(xiàn)了一些不同:在父類的構(gòu)造函數(shù)中的內(nèi)容是不會繼承的,父類的構(gòu)造函數(shù)不會被調(diào)用,子類(prototype中)已有的方法也會丟失!繼續(xù)看下去,將Ext.extend下面的代碼替換成:
復(fù)制代碼 代碼如下:

var stu = new Student('01');
Student.override({ print: function() { alert('I am a student'); } });
stu.override({ print: function() { alert('I am a bad student,but I won\'t affect others'); } });
stu.print();
stu.showAge();
var stu2 = new Student();
stu2.print();

這里的函數(shù)都能夠按預(yù)期輸出,showAge是執(zhí)行的父類的方法,stu.print是執(zhí)行的stu.override中指定的方法,而stu2執(zhí)行的是Student.override中指定的方法。到這里,我們已經(jīng)大概能猜出extend是如何實現(xiàn)的了。下面看它真正的源代碼,這個方法位于Ext.js中,代碼和注釋如下:extend : function(){
復(fù)制代碼 代碼如下:

// inline overrides
var io = function(o){ //注意這個方法的this,僅看這里并不知道這個this是什么,下面這個io會被賦值給sbp.override,也就是子類的prototype
for(var m in o){ //從而每個子類的對象的override都會指向這個方法,如果子類對象調(diào)用了override,那么這個this就是子類的對象了。也就是
this[m] = o[m]; //上面的例子中stu.override表現(xiàn)出來的效果,僅對當(dāng)前對象有效。從這里可以看出,override不僅僅是傳統(tǒng)意義上的覆蓋,完全也可以
} //用來添加新方法。
};
var oc = Object.prototype.constructor;

return function(sb, sp, overrides){
if(Ext.isObject(sp)){ //是在檢測當(dāng)前使用的是哪個版本的重構(gòu)函數(shù)。如果sp實際上是overrides,就做些替換工作,讓變量的實際意義和名稱相符合。
overrides = sp;
sp = sb;
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; //這個沒看懂……
}
var F = function(){},
sbp,
spp = sp.prototype;

F.prototype = spp; //F是父類的一個“干凈”拷貝,所謂干凈,是指它不會把父類中在構(gòu)造函數(shù)內(nèi)部定義的屬性帶過來。 //例如 Person=function() // {this.privateFn=new function{ some code goes here}} //那么這個privateFn對子類是不可見的,所以在構(gòu)造函數(shù)中利用this定義的屬性都相當(dāng)于是類的私有變量。
sbp = sb.prototype = new F(); //將子類的prototype設(shè)置為父類的prototype,繼承的核心步驟。 sbp.constructor=sb; //設(shè)置正確的構(gòu)造函數(shù)指向,見 JavaScript繼承詳解
sb.superclass=spp; //設(shè)置父類
if(spp.constructor == oc){ //沒看懂……,這個是干嘛用的?望高人指點
spp.constructor=sp;
}
sb.override = function(o){ //子類的重寫方法,這個重寫方法是函數(shù)的重寫方法。它修改的是prototype。
Ext.override(sb, o); //見最后。
};
sbp.superclass = sbp.supr = (function(){ //設(shè)置原型的父類
return spp;
});
sbp.override = io; //給子類的prototype提供override方法,這樣單個實體也可以覆蓋,它修改的是實體對象。注意和上面的sb的override區(qū)分。
Ext.override(sb, overrides); //重寫
sb.extend = function(o){return Ext.extend(sb, o);}; //給子類提供extend方法,以實現(xiàn)多重繼承
return sb; //返回子類。
};
}();

下面是Ext.override的代碼,比較明了的,和那個inline override相比,它就是修改的prototype:override :
復(fù)制代碼 代碼如下:

function(origclass, overrides){
if(overrides){
var p = origclass.prototype;
Ext.apply(p, overrides);
if(Ext.isIE && overrides.hasOwnProperty('toString')){ // 這個是什么?IE的特殊點?
p.toString = overrides.toString;
}
}
}

現(xiàn)在就可以開始正式介紹Extjs的事件模型了。和其他語言事件類似,首先要為一個類定義事件,其他語言(例如C#)的事件一般有一個專門的event類型,event類型實際上可以看作是委托的數(shù)組,當(dāng)然委托實際上是函數(shù),添加時間監(jiān)聽器(listener),就是想委托數(shù)組中添加委托(函數(shù)),所謂觸發(fā)事件就是把數(shù)組中的函數(shù)統(tǒng)統(tǒng)執(zhí)行一遍。Javascript也是類似的,只是Javascript的函數(shù)比那些語言強大靈活的多,因此也不需要什么event類型了。Javascript的事件看起來就像一個字符串(它內(nèi)部應(yīng)該也是保留了一個數(shù)組的),可以通過Observale.addEvents方法添加事件,通過Observale.fireEvent觸發(fā)事件,通過Observale.addListner增加事件監(jiān)聽器。下面舉一個沒什么意義卻能說明問題的例子。
復(fù)制代碼 代碼如下:

Odder = function(min, max) {
this.min = min;
this.max = max;
this.addEvents('onFindOdd');
}
Ext.extend(Odder, Ext.util.Observable, { run:
function() {
for (var i = this.min; i < this.max; i++) {
if (i % 2 != 0) {
this.fireEvent('onFindOdd',i);
}
}
}
});
var p = new Odder(4, 8);
p.addListener('onFindOdd',function(n){alert(n);});
p.run();

Odder是這么一個類,它通過一個構(gòu)造函數(shù)傳入一個范圍,然后尋找這個范圍內(nèi)的所有奇數(shù),每找到一個就觸發(fā)一個事件。我給它加一個事件處理程序,把它找到的奇數(shù)alert出來。 要注意,這里的事件處理程序的參數(shù)只能靠程序員自己保持一致,它不像委托那樣強類型。

注意,我沒有采用官網(wǎng)上的例子:
復(fù)制代碼 代碼如下:

Employee = Ext.extend(Ext.util.Observable, {
constructor: function(config){
this.name = config.name;
this.addEvents({
"fired" : true,
"quit" : true
});

// Copy configured listeners into *this* object so that the base class's
// constructor will add them.
this.listeners = config.listeners;

// Call our superclass constructor to complete construction process.
Employee.superclass.constructor.call(config)
}
});This could then be used like this:
var newEmployee = new Employee({
name: employeeName,
listeners: {
quit: function() {
// By default, "this" will be the object that fired the event.
alert(this.name + " has quit!");
}
}
});

我覺得官網(wǎng)上的例子內(nèi)部還有文章,它的重載項中包含了constructor屬性,給人的感覺是是重載了父類的構(gòu)造函數(shù),然后子類就會調(diào)用這個構(gòu)造函數(shù)來創(chuàng)建,其實不是的,它改變了Javascript本身的行為,這個就和我上面標(biāo)注的沒有看懂的那幾句代碼有關(guān)系。下回再討論。

相關(guān)文章

最新評論

青川县| 安泽县| 阿巴嘎旗| 莒南县| 岐山县| 沙坪坝区| 马山县| 元氏县| 平和县| 榆中县| 玛曲县| 万荣县| 永善县| 庆城县| 大英县| 蛟河市| 南宫市| 扎囊县| 神农架林区| 梨树县| 长顺县| 莆田市| 颍上县| 青海省| 抚顺县| 霍邱县| 安陆市| 连平县| 拜城县| 随州市| 旌德县| 普安县| 鄯善县| 景德镇市| 邳州市| 奉化市| 溧水县| 许昌县| 定结县| 中宁县| 盱眙县|