讀GI源碼、學(xué)JS編程——JavaScript中的事件實現(xiàn)(完整版)。
Posted on 2007-08-03 10:59 love1563 閱讀(331) 評論(0) 編輯 收藏 所屬分類: JSP/Servlets/JSF???????? SOA這盤菜被個大廠商炒了又炒,WebService漸漸成為標(biāo)準(zhǔn)的傳輸方式,Soap被越來越多的人認(rèn)識。這個時候人們發(fā)現(xiàn)JavaScript能夠調(diào)用WebService,于是有人開始試水了。不得不說用Javascipt完全可以作為為UI層的骨架,UI層的邏輯開發(fā)對于Javascipt簡直就是得心應(yīng)手,顯示更不用說,傳輸用WebService,哈哈,不再需要那么多WebForm控件,讓C#去更多的關(guān)注如何實現(xiàn)業(yè)務(wù)去吧。
???????? 但對于JavaScript很多人不是很了解,尤其是對于大型RIA程序來說,一堆堆的腳本對于習(xí)慣了C#的程序員簡直就是惡夢。就像每個人當(dāng)初學(xué)C#一樣,Petshop是一門不可多得的教材,當(dāng)TIBCO宣布GI開源的時候,人們發(fā)現(xiàn)這才是JavaScript中最好最重量級的教材。我想一起與大家學(xué)習(xí)GI中值得學(xué)習(xí)的部分,學(xué)習(xí)Javascipt怎么在大型RIA中發(fā)揮作用。
?再簡單介紹一下GI_Builder,GI_Builder是TIBCO公司開發(fā)的一套基于Javascipt開發(fā)的用開發(fā)開JavaScript的IDE,當(dāng)然也包括一套Framework,類似于VS2005,只需要你拖拖拽拽就能實現(xiàn)頁面上的,實現(xiàn)很多大家夢寐以求的Javascipt端的控件,Tab,Tree,Grid,甚至于更佳神奇的在Firefox下用SVG比表示,在IE下用VML表示的Chart。相信這些東西如何實現(xiàn)肯定誰都非常感興趣。
?好吧我們先從寫基礎(chǔ)的開始,看看大程序為了實現(xiàn)整個功能的運行都做了些什么。大多數(shù)人都知道,Ajax程序是以事件驅(qū)動為基礎(chǔ)的,而實現(xiàn)一個事件的注冊和廣播也是很多框架中必要的設(shè)計,GI中是如何實現(xiàn)事件的機制的呢。
???????? 我們先來看這樣一段偽事件的實現(xiàn):
{
????//聲明事件
????this.onAdd=function(){return?false;}
????this.Add=function(a,b)
????{
????????var?c=a+b;
????????//執(zhí)行事件
????????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);
????}
}

于是乎Asp.net Ajax中出現(xiàn)了這樣的一個東西:
{
????return?function(){return?method.apply(instance,arguments);};
}
這個東東的確好用,我經(jīng)常用他也。一個apply成為了我們救星,可是又一個問題出現(xiàn)了我們在.net中可以一個勁兒的+=然后再+=,最后全都執(zhí)行了,怎么一下子搞那么多事件。如何才能讓Javascript中也實現(xiàn)這樣的復(fù)雜機制呢?要想知道GI中如何實現(xiàn),且聽下回分解。
太困了,明天接著寫吧,還要上班、上班呢啊。
---------------------------------------------------------------------12小時后----------------------------------------------------------------------------
?
書接上回,咱們接著說事件的實現(xiàn),一醉解千愁同志正解,就原理來說的確是一個Array就能來搞定,當(dāng)然GI中為了實現(xiàn)不同的事件時用一個Object來實現(xiàn)的。但具體怎么實現(xiàn)的呢,還是來看GI的同志們怎么實現(xiàn)的吧。
在JSX30.js中有這樣的一些代碼:
然后當(dāng)然就是事件的注冊了,事件的注冊需要什么?需要知道注冊到什么事件上就是onXXX,還需要知道綁定到哪個方法上,于是乎evtPub._subscribe = function(strSubject, objTarget, strMethod)方法出現(xiàn)了
????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]);
};
看這些參數(shù),首先strSubject就是我們所說的onXXX,關(guān)于后面的兩個參數(shù)是什么,我們來看看事件是如何執(zhí)行的再說。
來廣播了:
????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中自己實現(xiàn)的一個Event類,里面有個屬性subject就是那個onXXX。好了,看這個方法中,在執(zhí)行事件之前做了個判斷也就是說objTarget會有兩種形式Object和function所以說他注冊的話也會有兩種方法咯:
objApp._queue._subscribe("qstart", objApp._progress, "onQueueStart");
objApp._queue._subscribe("qdone", function() {…});
當(dāng)然第一種方式是主要的使用方式,objTarget是調(diào)用方法所屬的引用,strMethod是要調(diào)用的方法
另外,還需要看以下這個list = list.concat();我一直都不太明白,我猜想這個是為了線程安全的,在publish的時候如果再注銷這個事件就會發(fā)生問題。還請高人指點……
最后當(dāng)然是事件的注銷了:
????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….
也就是說在你的類里面需要執(zhí)行以下import的方法,然后你的類里面就這些方法就都用了,不就是個call()的功能-_-b…