無為

          無為則可為,無為則至深!

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks
          首先yahoo在后支持;
          mail list也比較活躍,但好象高人關(guān)注的不多;
          出現(xiàn)時(shí)間不常,參考了太多開源類庫如prototype.js及擴(kuò)展項(xiàng)目,dojo....;
          項(xiàng)目測(cè)試做的不錯(cuò)(yahoo用了它的不少);
          太多的靈感(yahoo中界面,用戶交互設(shè)計(jì)高人應(yīng)該提了不少建議)
          容易上手(代碼寫的比較累贅,可能是0.10.0版本吧);

          不敢再與其它類庫比較了,怕招罵。呵。總之還是我的那個(gè)觀點(diǎn),javascript代碼太容易抄襲了,所以類庫的可”重構(gòu)性“很是重要。YUI做的還行吧。

          現(xiàn)在切入正題
          一、dom.js可能這部分與prototype.js某些功能差不多,但實(shí)現(xiàn)感覺比prototype.js更好些(個(gè)人觀點(diǎn),別咂我哦)
          ? 1、通過id,className,TagName等返回DOM元素的方法。getElementsBy (<Function> method, <String> tag, <String/HTMLElement> root) 看看這個(gè)方法很有意思。你可以通過這個(gè)方法定制你取的dom元素的方法。
          ???? getElementsBy: function(method, tag, root) {
          ???????? tag = tag || '*';
          ???????? root = this.get(root) || document;
          ????????
          ???????? var nodes = [];
          ???????? var elements = root.getElementsByTagName(tag);
          ????????
          ???????? if ( !elements.length && (tag == '*' && root.all) ) {
          ??????????? elements = root.all; // IE < 6
          ???????? }
          ????????
          ???????? for (var i = 0, len = elements.length; i < len; ++i)
          ???????? {
          ??????????? if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; }
          ???????? }

          ???????? return nodes;
          ????? },
          ? 2、修改dom元素的className.
          ???? 無非是增,刪,改,查。注意 YUI中可以傳入id或dom的數(shù)組來處理。通過匿名函數(shù)來實(shí)現(xiàn)。絕對(duì)經(jīng)典。
          ?? 詳細(xì)看
          batch: function(el, method, o, override) {
          ???????? el = this.get(el);
          ???????? var scope = (override) ? o : window;
          ????????
          ???????? if (!el || el.tagName || !el.length)
          ???????? { // is null or not a collection (tagName for SELECT and others that can be both an element and a collection)
          ??????????? return method.call(scope, el, o);
          ???????? }
          ????????
          ???????? var collection = [];
          ????????
          ???????? for (var i = 0, len = el.length; i < len; ++i)
          ???????? {
          ??????????? collection[collection.length] = method.call(scope, el[i], o);
          ???????? }
          ????????
          ???????? return collection;
          ????? },
          3、直接對(duì)DOM元素的style的修改
          ?? 如果修改dom.style細(xì)粒度屬性。className就不合適了。還好提供了這些方法。并且跨瀏覽器支持的不錯(cuò),很多屬性我都不知道,看代碼才明白各個(gè)瀏覽器對(duì)css支持有不同,如property == 'opacity' && el.filters

          ?? 也用batch支持?jǐn)?shù)組方式。
          YAHOO.util.Dom.setStyle(["div1","div2","div3"], "color","red");
          4、對(duì)dom元素位置和大小的函數(shù)
          對(duì)于偶喜歡擺弄webgis,google maps之類的當(dāng)然最喜歡這部分了。
          可以得到或修改dom元素的x,y。YUL的animation、dragdrop等大量用到這個(gè)東西。當(dāng)然這部分也做了大量跨瀏覽器支持。
          對(duì)于DOM的大小,YUI定義了個(gè)YAHOO.util.Region包,也就是個(gè)矩形,定義了contains(包含),intersect(相交方法)。呵呵,和prototype.js中的within,overlap差不多。? 其實(shí)用這個(gè)函數(shù)實(shí)現(xiàn)google個(gè)性化定義的拖是個(gè)好不錯(cuò)。
          5、其它方法
          getViewportHeight ()?? getDocumentHeight?? 不知道有什么不同,待偶查查資料去。
          getViewportWidth ()?? getDocumentWidth
          inDocument? 是否document對(duì)象
          isAncestor: function(haystack, needle) 檢查dom對(duì)象是否是另一個(gè)對(duì)象的父節(jié)點(diǎn)
          ...................

          二、event.js
          關(guān)于注冊(cè)事件的問題我也寫過不少,YUI實(shí)現(xiàn)的是不錯(cuò)的,通過CustomEvent也可以模擬實(shí)現(xiàn)AOP的方法攔截。當(dāng)然dojo的實(shí)現(xiàn)還是老大。
          主要分為兩部分。
          1、事件注冊(cè)
          YAHOO.util.Event.addListener: function(el, sType, fn, oScope, bOverride);
          參數(shù)分別是: dom的ID或元素本身;類型(click,mouseover等);函數(shù);誰調(diào)用這個(gè)函數(shù);是否覆蓋

          看例子,注意最后兩個(gè)參數(shù),只有在bOverride為true時(shí)才有效。

          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
          <html>
          <head>
          <title>test</title>
          <script type="text/javascript" src="../../build/yahoo/yahoo.js"></script>
          <script type="text/javascript" src="../../build/event/event.js"></script>
          <script type="text/javascript" src="../../build/dom/dom.js"></script>
          <script type="text/javascript">
          var name="window.name";
          var Fun={
          ??? name : "funName",
          ?doClick: function(){
          ?????? alert(this.name);
          ?}
          }
          var init = function() {
          ?? YAHOO.util.Event.addListener(test, 'click', Fun.doClick);
          ?? YAHOO.util.Event.addListener(test, 'click', Fun.doClick,Fun,false);
          ?? YAHOO.util.Event.addListener(test, 'click', Fun.doClick,Fun,true);
          ?? YAHOO.util.Event.addListener(test, 'click', Fun.doClick,window,true);
          };

          YAHOO.util.Event.addListener(window, 'load',init);
          </script>
          </head>
          <body>
          <div id="test" name="dom name">
          ?? 誰敢點(diǎn)我
          </div>
          </body>
          </html>

          小TIP:yahoo的事件注冊(cè)支持多個(gè)dom元素的事件注冊(cè),只要第一個(gè)參數(shù)是 dom對(duì)象的數(shù)組就可以了。
          ????? 也支持延遲注冊(cè),也就是你在dom元素還沒有加載的時(shí)候注冊(cè)事件,但有個(gè)條件,第一個(gè)參數(shù)必須是字符串(dom的id),這里就不支持多個(gè)元素的注冊(cè)了。? YUI會(huì)在window.onload方法里把所有延遲注冊(cè)的事件注冊(cè)了(太繞了)。

          2、CustomEvent,Subscriber
          ? 一個(gè)觀察者模式的javascript的實(shí)現(xiàn),要想用好,難度不小,yahoo官網(wǎng)提供的例子也極度白癡。但在YUI的animation,AutoComplete等里面應(yīng)用了這個(gè)玩意,很有創(chuàng)意。在控件內(nèi)部定義的很多CustomEvent,當(dāng)控件狀態(tài)改變時(shí),觸發(fā)CustomEvent里面的Subscriber方法。有點(diǎn)AOP的感覺。
          ? 感覺這類傳統(tǒng)c/s的設(shè)計(jì)模式用javascrit來實(shí)現(xiàn)對(duì)于我們普通開發(fā)者來說沒什么好處,反而讓代碼更加難懂,類庫里面用用就得了,。無論什么地方用,把a(bǔ)jax變成當(dāng)成c/s架構(gòu)的變成思想是我們應(yīng)該提前樹立的。
          ? 我也只能通過例子說說定制事件了;下面代碼(拷貝到html可以直接運(yùn)行ie,ff下測(cè)試通過)是一個(gè)簡(jiǎn)單的AOP實(shí)現(xiàn),象這種弱類型,參數(shù)可以隨便變化的語言實(shí)現(xiàn)類似AOP的功能是很尷尬的。就當(dāng)練手的。

          ??? 開發(fā)ajax時(shí),把瀏覽器當(dāng)成桌面開發(fā),那時(shí),觀察者,MVC就很實(shí)用了.


          <body>
          <div id="log"></div>
          </body>
          <SCRIPT LANGUAGE="JavaScript">
          function log(msg){
          ??? var obj=document.getElementById("log");
          ?obj.innerHTML+=msg+"<br>";//你們可別這么寫啊
          }
          var YAHOO={};
          YAHOO.util={};
          YAHOO.util.CustomEvent = function(type, oScope) {
          ??? this.type = type;
          ??? this.scope = oScope || window;
          ??? this.subscribers = [];
          ??? if (YAHOO.util.Event) {
          ??????? YAHOO.util.Event.regCE(this);
          ??? }
          };

          YAHOO.util.CustomEvent.prototype = {
          ??? subscribe: function(fn, obj, bOverride) {
          ??????? this.subscribers.push( new YAHOO.util.Subscriber(fn, obj, bOverride) );
          ??? },
          ??? unsubscribe: function(fn, obj) {
          ??????? var found = false;
          ??????? for (var i=0, len=this.subscribers.length; i<len; ++i) {
          ??????????? var s = this.subscribers[i];
          ??????????? if (s && s.contains(fn, obj)) {
          ??????????????? this._delete(i);
          ??????????????? found = true;
          ??????????? }
          ??????? }

          ??????? return found;
          ??? },
          ??? fire: function() {
          ??????? for (var i=0, len=this.subscribers.length; i<len; ++i) {
          ??????????? var s = this.subscribers[i];
          ??????????? if (s) {
          ??????????????? var scope = (s.override) ? s.obj : this.scope;
          ??????????????? s.fn.call(scope, this.type, arguments, s.obj);
          ??????????? }
          ??????? }
          ??? },
          ??? unsubscribeAll: function() {
          ??????? for (var i=0, len=this.subscribers.length; i<len; ++i) {
          ??????????? this._delete(i);
          ??????? }
          ??? },
          ??? _delete: function(index) {
          ??????? var s = this.subscribers[index];
          ??????? if (s) {
          ??????????? delete s.fn;
          ??????????? delete s.obj;
          ??????? }

          ??????? delete this.subscribers[index];
          ??? }
          };
          YAHOO.util.Subscriber = function(fn, obj, bOverride) {
          ??? this.fn = fn;
          ??? this.obj = obj || null;
          ??? this.override = (bOverride);
          };
          YAHOO.util.Subscriber.prototype.contains = function(fn, obj) {
          ??? return (this.fn == fn && this.obj == obj);
          };

          /////////////////////////////////////////////////////////////////////////
          /////////////////////////////////////////////

          var ProxyFunction=function(fn,scope){
          ?? this.fn=fn;
          ?? this.scope=scope||window;
          ?? this.beforeEvent=new YAHOO.util.CustomEvent("beforeEvent",this.scope);
          ?? this.afterEvent=new YAHOO.util.CustomEvent("afterEvent",this.scope);
          }
          ProxyFunction.prototype.addBefore=function(fn, obj){
          ?? this.beforeEvent.subscribe(fn, obj,true);
          }
          ProxyFunction.prototype.addAfter=function(fn, obj){
          ?? this.afterEvent.subscribe(fn, obj,true);
          }
          ProxyFunction.prototype.execute=function(){
          ??? this.beforeEvent.fire();
          ??? var ret=this.fn.apply(this.scope, arguments);//我這里面保證arguments為fun被代理函數(shù)的參數(shù)列表
          ?log("execute......");
          ?log("execute after 前 ret="+ret);
          ?var temp={result:ret};//為了修改執(zhí)行結(jié)果......
          ??? this.afterEvent.fire(temp);
          ?return temp.result;
          }
          var Logic={
          ??? name: "Logic private value",
          ??? fun : function (p){
          ???? log("被代理方法訪問this.name="+this.name);
          ??????? return "fun "+p+" execute!";
          ??? }
          }
          function Interceptor(){
          ??? this.name="Interceptor? private value";
          }
          Interceptor.prototype.before=function(){
          ??? log("before...... this.name="+this.name);
          ?log("before...... arguments[0]="+arguments[0]+" arguments[1]="+arguments[1]+" arguments[2]="+arguments[2]+" arguments[3]="+arguments[3]);
          ?log("before...... arguments[2]="+arguments[2]+" 為addBefore/addAfter中最后一個(gè)參數(shù)");
          ??? log("before......");
          }
          Interceptor.prototype.after=function(){
          ??? log("after......this.name="+this.name);
          ?log("after......arguments[1]="+arguments[1][0] +"? 可以在這修改返回的結(jié)果");
          ?arguments[1][0].result="修改結(jié)果";
          ??? log("after......");
          }

          var funProxy=new ProxyFunction(Logic.fun,Logic);//參數(shù)[0] 需要代理的函數(shù) 參數(shù)[1] 執(zhí)行這個(gè)函數(shù)的對(duì)象
          var myInterceptor=new Interceptor();//新建攔截器

          funProxy.addBefore(myInterceptor.before,window);//注意第三個(gè)參數(shù)
          funProxy.addBefore(myInterceptor.before,myInterceptor);
          funProxy.addAfter(myInterceptor.after,Logic);
          var result=funProxy.execute("參數(shù)");
          log(result);
          </SCRIPT>



          凡是有該標(biāo)志的文章,都是該blog博主Caoer(草兒)原創(chuàng),凡是索引、收藏
          、轉(zhuǎn)載請(qǐng)注明來處和原文作者。非常感謝。

          posted on 2006-06-24 08:25 草兒 閱讀(251) 評(píng)論(0)  編輯  收藏 所屬分類: ajax
          主站蜘蛛池模板: 涟源市| 阿勒泰市| 都兰县| 丽水市| 平谷区| 兴安县| 奇台县| 兴安盟| 黄骅市| 武乡县| 左云县| 元谋县| 武陟县| 桐庐县| 额尔古纳市| 汤原县| 天台县| 星座| 巴塘县| 启东市| 三明市| 道真| 武宣县| 方山县| 鄢陵县| 平塘县| 瑞安市| 孟津县| 玉田县| 东海县| 独山县| 古浪县| 黑河市| 汶上县| 丰都县| 合川市| 太白县| 石屏县| 定边县| 瓮安县| 连州市|