?
???????? JavaScript雖著Ajax應用越來越多,也變得越來越重要,越來越多的“網絡版”軟件以其眼花繚亂的異步加載刷新讓人感觸到Ajax的威力,越來越多的程序員們也開始關注于JavaScript的學習,以至于慢慢的發現JavaScript完全由能力擔任所有UI層編碼的重任。
???????? SOA這盤菜被個大廠商炒了又炒,WebService漸漸成為標準的傳輸方式,Soap被越來越多的人認識。這個時候人們發現JavaScript能夠調用WebService,于是有人開始試水了。不得不說用Javascipt完全可以作為為UI層的骨架,UI層的邏輯開發對于Javascipt簡直就是得心應手,顯示更不用說,傳輸用WebService,哈哈,不再需要那么多WebForm控件,讓C#去更多的關注如何實現業務去吧。
???????? 但對于JavaScript很多人不是很了解,尤其是對于大型RIA程序來說,一堆堆的腳本對于習慣了C#的程序員簡直就是惡夢。就像每個人當初學C#一樣,Petshop是一門不可多得的教材,當TIBCO宣布GI開源的時候,人們發現這才是JavaScript中最好最重量級的教材。我想一起與大家學習GI中值得學習的部分,學習Javascipt怎么在大型RIA中發揮作用。?再簡單介紹一下GI_Builder,GI_Builder是TIBCO公司開發的一套基于Javascipt開發的用開發開JavaScript的IDE,當然也包括一套Framework,類似于VS2005,只需要你拖拖拽拽就能實現頁面上的,實現很多大家夢寐以求的Javascipt端的控件,Tab,Tree,Grid,甚至于更佳神奇的在Firefox下用SVG比表示,在IE下用VML表示的Chart。相信這些東西如何實現肯定誰都非常感興趣。
?好吧我們先從寫基礎的開始,看看大程序為了實現整個功能的運行都做了些什么。大多數人都知道,Ajax程序是以事件驅動為基礎的,而實現一個事件的注冊和廣播也是很多框架中必要的設計,GI中是如何實現事件的機制的呢。
???????? 我們先來看這樣一段偽事件的實現:
ClassA=function()
{
????//聲明事件
????this.onAdd=function(){return?false;}
????this.Add=function(a,b)
????{
????????var?c=a+b;
????????//執行事件
????????if(typeof(this.onAdd)=="function")this.onAdd();
????????return?c;
????}
}
ClassB=function()
{
????this.AlertAdd=function()
????{
????????this;?//這里讓大家看點東西,嘿嘿
????????alert("Add");
????}
????this.Test=function()
????{
????????var?a=new?ClassA();
????????//綁定事件
????????a.onAdd=this.AlertAdd;
????????a.Add(1,1);
????}
}
???
由于Javascipt太靈活了,所以我有了可乘之機,用了一個方法,然后動態的替換它,這樣就執行的時候就可以動態的執行我的那個方法咯。哈哈,好像挺完美的吧,這么簡單個東西這樣就搞定了,可惜這里有點問題要解決,那就是this;這個東西,呵呵。由于AlertAdd這個方法里面的內容都指向了onAdd方法了,確切地說他是在ClassA的scope里面運行的,這里的this就變成了ClassA了,DOM中的事件也和這種情況差不多,具體和this的作用范圍有關,亂了吧,想必很多人都遇到過這樣的問題,哈。

于是乎Asp.net Ajax中出現了這樣的一個東西:
function?Function.createDelegate(instance,method)
{
????return?function(){return?method.apply(instance,arguments);};
}
這個東東的確好用,我經常用他也。一個apply成為了我們救星,可是又一個問題出現了我們在.net中可以一個勁兒的+=然后再+=,最后全都執行了,怎么一下子搞那么多事件。如何才能讓Javascript中也實現這樣的復雜機制呢?要想知道GI中如何實現,且聽下回分解。
太困了,明天接著寫吧,還要上班、上班呢啊。
---------------------------------------------------------------------12小時后----------------------------------------------------------------------------
? 書接上回,咱們接著說事件的實現,一醉解千愁同志正解,就原理來說的確是一個Array就能來搞定,當然GI中為了實現不同的事件時用一個Object來實現的。但具體怎么實現的呢,還是來看GI的同志們怎么實現的吧。
在JSX30.js中有這樣的一些代碼:
然后當然就是事件的注冊了,事件的注冊需要什么?需要知道注冊到什么事件上就是onXXX,還需要知道綁定到哪個方法上,于是乎evtPub._subscribe = function(strSubject, objTarget, strMethod)方法出現了
????/*?@jsxobf-clobber?*/????
????evtPub._subscribe?=?function(strSubject,?objTarget,?strMethod)?{
??????if?(this._evtpubreg?==?null)
????????/*?@jsxobf-clobber?*/????
????????this._evtpubreg?=?{};
??????var?list?=?this._evtpubreg[strSubject];
??????if?(list?==?null)
????????list?=?this._evtpubreg[strSubject]?=?[];
??????list.push([objTarget,?strMethod]);
};
看這些參數,首先strSubject就是我們所說的onXXX,關于后面的兩個參數是什么,我們來看看事件是如何執行的再說。
來廣播了:
????/*?@jsxobf-clobber?*/????
????evtPub._publish?=?function(objEvent)?{
??????if?(this._evtpubreg?!=?null)?{
????????var?list?=?this._evtpubreg[objEvent.subject];
????????if?(list)?{
??????????if?(objEvent.target?==?null)?
????????????objEvent.target?=?this;
??????????list?=?list.concat();?//?defensive?copy
??????????for?(var?i?=?0;?i?<?list.length;?i++)?{
????????????if?(typeof(list[i][0])?==?"function")
??????????????list[i][0](objEvent);
????????????else
??????????????list[i][0][list[i][1]](objEvent);
??????????}
????????}
??????}
};
先聲明一下,objEvent是GI中自己實現的一個Event類,里面有個屬性subject就是那個onXXX。好了,看這個方法中,在執行事件之前做了個判斷也就是說objTarget會有兩種形式Object和function所以說他注冊的話也會有兩種方法咯:
objApp._queue._subscribe("qstart", objApp._progress, "onQueueStart");
objApp._queue._subscribe("qdone", function() {…});
當然第一種方式是主要的使用方式,objTarget是調用方法所屬的引用,strMethod是要調用的方法
另外,還需要看以下這個list = list.concat();我一直都不太明白,我猜想這個是為了線程安全的,在publish的時候如果再注銷這個事件就會發生問題。還請高人指點……
最后當然是事件的注銷了:
????/*?@jsxobf-clobber?*/????
????evtPub._unsubscribe?=?function(objTarget)?{
??????if?(this._evtpubreg?!=?null)?{
????????for?(var?subject?in?this._evtpubreg)?{
??????????var?list?=?this._evtpubreg[subject];
??????????for?(var?i?=?0;?i?<?list.length;?i++)?{
????????????if?(list[i]?==?objTarget)
??????????????list.splice(i--,?1);
??????????}
????????}
??????}
};
????/*?@jsxobf-clobber?*/????
????evtPub._evtcleanup?=?function(objEvent)?{
??????delete?this._evtpubreg;
????};
????/*?@jsxobf-clobber?*/????
????evtPub._import?=?function(objTarget)?{
??????objTarget._subscribe?=?this._subscribe;
??????objTarget._unsubscribe?=?this._unsubscribe;
??????objTarget._publish?=?this._publish;
??????objTarget._evtcleanup?=?this._evtcleanup;
????};
注銷,值得一提的就是import方法,這是什么?繼承-_-b….
也就是說在你的類里面需要執行以下import的方法,然后你的類里面就這些方法就都用了,不就是個call()的功能-_-b…