首頁  >  文章  >  web前端  >  javascript如何實作extjs事件的原理實例詳解

javascript如何實作extjs事件的原理實例詳解

伊谢尔伦
伊谢尔伦原創
2017-07-20 15:33:481426瀏覽

Extjs實作繼承的函數是一個很核心的函數Ext.extend,extend方法有兩個重構版本,第一個接受兩個參數,第一個是extend( Function superclass, Object overrides ) ,第二個是extend( Function subclass, Function superclass,Object overrides ) : Function,第二個版本是在subclass的基礎上。 superclass就是超類別的建構函數,overrides是一個對象,裡邊的屬性就是要覆寫父類別的屬性。繼承了父類別的子類別具有父類別的prototype中的所有方法。而子類別可以覆寫父類別的方法(override),更進一步,子類別的每個物件也可以覆寫父類別的方法。其實我覺得這個函數沒什麼作用,修改prototype的效果是等效的,當然,extjs的目的肯定是要把prototype這個神奇的東西完全屏蔽起來,使程式設計師能夠像處理其他語言一樣來處理Javascript。當然,即使如此,它的繼承和一般的繼承還是有些不同的,下面先看個例子,準備好一個Person類別:

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(); !!沒有結果! stu沒有name的定義stu.fn(); !!沒有結果stu.showID(); !!!還是沒有結果到此我們已經發現了一些不同:在父類的構造函數中的內容是不會繼承的,父類別的建構子不會被調用,子類別(prototype中)已有的方法也會遺失!繼續看下去,將Ext.extend下面的程式碼替換成: 

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();

這裡的函數都能夠如預期輸出,showAge是執行的父類別的方法,stu.print是執行的stu.override中指定的方法,而stu2執行的是Student.override中指定的方法。到這裡,我們已經大概能猜出extend是如何實現的了。下面看它真正的原始碼,這個方法位於Ext.js中,程式碼和註解如下:extend : function(){ 

// inline overrides 
var io = function(o){ //注意这个方法的this,仅看这里并不知道这个this是什么,下面这个io会被赋值给sbp.override,也就是子类的prototype 
for(var m in o){ //从而每个子类的对象的override都会指向这个方法,如果子类对象调用了override,那么这个this就是子类的对象了。也就是 
this[m] = o[m]; //上面的例子中stu.override表现出来的效果,仅对当前对象有效。从这里可以看出,override不仅仅是传统意义上的覆盖,完全也可以 
} //用来添加新方法。 
}; 
var oc = Object.prototype.constructor; 
return function(sb, sp, overrides){ 
if(Ext.isObject(sp)){ //是在检测当前使用的是哪个版本的重构函数。如果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是父类的一个“干净”拷贝,所谓干净,是指它不会把父类中在构造函数内部定义的属性带过来。 //例如 Person=function() // {this.privateFn=new function{ some code goes here}} //那么这个privateFn对子类是不可见的,所以在构造函数中利用this定义的属性都相当于是类的私有变量。 
sbp = sb.prototype = new F(); //将子类的prototype设置为父类的prototype,继承的核心步骤。 sbp.constructor=sb; //设置正确的构造函数指向,见 JavaScript继承详解 
sb.superclass=spp; //设置父类 
if(spp.constructor == oc){ //没看懂……,这个是干嘛用的?望高人指点 
spp.constructor=sp; 
} 
sb.override = function(o){ //子类的重写方法,这个重写方法是函数的重写方法。它修改的是prototype。 
Ext.override(sb, o); //见最后。 
}; 
sbp.superclass = sbp.supr = (function(){ //设置原型的父类 
return spp; 
}); 
sbp.override = io; //给子类的prototype提供override方法,这样单个实体也可以覆盖,它修改的是实体对象。注意和上面的sb的override区分。 
Ext.override(sb, overrides); //重写 
sb.extend = function(o){return Ext.extend(sb, o);}; //给子类提供extend方法,以实现多重继承 
return sb; //返回子类。 
}; 
}();

下面是Ext.override的程式碼,比較明了的,和那個inline override相較,它就是修改後的prototype:override : 

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

現在就可以開始正式介紹Extjs的事件模型了。和其他語言事件類似,首先要為一個類別定義事件,其他語言(例如C#)的事件一般有一個專門的event類型,event類型實際上可以看作是委託的數組,當然委託實際上是函數,添加時間監聽器(listener),就是想委託數組中加入委託(函數),所謂觸發事件就是把數組中的函數統統執行一遍。 Javascript也是類似的,只是Javascript的函數比那些語言強大靈活的多,因此也不需要什麼event型別了。 Javascript的事件看起來像是字串(它內部應該也是保留了一個陣列的),可以透過Observale.addEvents方法加入事件,透過Observale.fireEvent觸發事件,透過Observale.addListner增加事件監聽器。以下舉一個沒什麼意義卻能說明問題的例子。 

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(&#39;onFindOdd&#39;,i); 
} 
} 
} 
}); 
var p = new Odder(4, 8); 
p.addListener(&#39;onFindOdd&#39;,function(n){alert(n);}); 
p.run();

Odder是這麼一個類,它透過一個建構函數傳入一個範圍,然後尋找這個範圍內的所有奇數,每找到一個就觸發一個事件。給它加一個事件處理程序,把它找到的奇數alert出來。 要注意,這裡的事件處理程序的參數只能靠程式設計師自己保持一致,它不像委託那樣強型別。 

以上是javascript如何實作extjs事件的原理實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn