Sun River
          Topics about Java SE, Servlet/JSP, JDBC, MultiThread, UML, Design Pattern, CSS, JavaScript, Maven, JBoss, Tomcat, ...
          posts - 78,comments - 0,trackbacks - 0
           

          Dojo API略解續

          dojo.lang.string

          dojo.string.substituteParams

          類似C#中的String.Format函數
          %{name}
          要保證與傳入的對象的名稱大小寫一致,否則會出異常
          Usage Example:
          dojo.string.substituteParams("%{0} - %{1} - %{2}", "a", "b", "c"); //will return "a - b - c"
          dojo.string.substituteParams("%{name}: %{value}", {name:"
          名稱",value:""}); //will return "名稱: "

          dojo.string.capitalize

          把每一個單詞的首字母大寫
          Usage Example:
          dojo.string.capitalize("show me love"); //will return "Show Me Love"

          dojo.string.isBlank

          判斷輸入字符串是否為空或全是空白字符,如果傳入對象為非字符串則也會返回true
          Usage Example:
          dojo.string.isBlank(" 1 "); //will return false

          dojo.string.escape

          參數1type,可傳值為: xml/html/xhtml, sql, regexp/regex, javas cript/js cript/js, ascii
          將按照所傳type對字符串進行編碼
          Usage Example:
          dojo.string.escape("html", "<input type='text' value='' />"); //will return "<input
          type='text' value='' />"
          dojo.string.encodeAscii
          dojo.string.escapeXml
          dojo.string.escapeSql
          dojo.string.escapeRegExp
          dojo.string.escapeJavas cript
          dojo.string.escapeString
          這些函數也就是 dojo.string.escape 所調用的,這里無需多說

          dojo.string.summary

          取得輸入字符串的縮略版本
          Usage Example:
          dojo.string.summary("1234567890", 5); //will return "12345..."

          dojo.string.endsWith

          判斷輸入字符串是否以指定的字符串結尾
          Usage Example:
          dojo.string.endsWith("abcde", "E"); //will return false
          dojo.string.endsWith("abcde", "E", true); //will return true

          dojo.string.endsWithAny

          判斷輸入字符串是否以指定的任意字符串結尾
          Usage Example:
          dojo.string.endsWithAny("abcde", "E", "e"); //will return true

          dojo.string.startsWith

          判斷輸入字符串是否以指定的字符串開頭
          Usage Example:
          dojo.string.startsWith("abcde", "A"); //will return false
          dojo.string.startsWith("abcde", "A", true); //will return true

          dojo.string.startsWithAny

          判斷輸入字符串是否以指定的任意字符串開頭
          Usage Example:
          dojo.string.startsWithAny("abcde", "A", "a"); //will return true

          dojo.string.has

          判斷輸入字符串是否含有任意指定的字符串
          Usage Example:
          dojo.string.has("abcde", "1", "23", "abc"); //will return true

          dojo.string.normalizeNewlines

          按要求轉換回車換行的格式
          Usage Example:
          dojo.string.normalizeNewlines("a"r"nb"r"n", ""r"); //will return "a"rb"r"

          dojo.string.splitEscaped

          將字符串按分隔符轉換為數組
          Usage Example:
          dojo.string.splitEscaped("a""_b_c", '_'); //will return ["a""_b", "c"]


          模塊:dojo.lang.func

          dojo.lang.hitch

          將指定的方法掛在指定的對象下并返回該方法
          Usage Example:
          func = {test: function(s) {alert(s)}};
          dojo.lang.mixin(func, {demo: dojo.lang.hitch(func, "test")});
          func.demo("demo and test are same method");

          dojo.lang.forward

          返回自身對象的指定名稱的方法引用
          Usage Example:
          func = {test: function(s) {alert(s)}, demo: dojo.lang.forward("test")};
          func.demo("demo and test are same method");

          dojo.lang.curry

          What is curry? 請參閱這篇文章:http://www.svendtofte.com/code/curried_javas cript/
          Usage Example:
          function add(a, b)
          {
          return a + b;
          }
          dojo.lang.curry(null, add, 2, 3); //will return 5
          dojo.lang.curry(null, add, 2)(3); //will return 5

          dojo.lang.curry(null, add)(2)(3); //will return 5
          dojo.lang.curry(null, add)()(2)(3); //will return 5

          dojo.lang.curryArguments

          dojo.lang.curry類似,但是可以選擇忽略掉前n個參數
          Usage Example:
          function add(a, b)
          {
          return a + b;
          }
          dojo.lang.curryArguments(null, add, [1,2,3,4,5], 2); //will return 7 (= 3 + 4)

          處理數組相關api

          dojo.lang.has

          判斷對象是否具有指定屬性,不過這個方法有用嗎,不如直接使用 if(name in obj)
          Usage Example:
          dojo.lang.has(dojo.lang, "has"); //will return true

          dojo.lang.isEmpty

          判斷對象或數組是否為空
          Usage Example:
          dojo.lang.isEmpty({a: 1}); //will return false
          dojo.lang.isEmpty([]); //will return true

          dojo.lang.map

          調用指定的方法處理指定的數組或字符串
          Usage Example:
          dojo.lang.map([1,2,3,4,5], function(x) { return x * x;}); //will return [1,4,9,16,25]

          dojo.lang.forEach

          遍歷指定的數組或字符串,并對其中的元素調用指定的方法
          Usage Example:
          dojo.lang.forEach("abc", function(x) { alert(x); });

          dojo.lang.every

          檢查指定的數組是否全部滿足指定方法的條件
          Usage Example:
          dojo.lang.every([1,-2,3], function(x) { return x > 0; }); //
          指定的數組不是全大于0的,因此返回false

          dojo.lang.some

          檢查指定的數組是否部分滿足指定方法的條件
          Usage Example:
          dojo.lang.some([1,-2,3], function(x) { return x > 0; }); //
          指定的數組有大于0的元素,因此返回true

          dojo.lang.filter

          根據指定的方法來過濾指定的數組
          Usage Example:
          dojo.lang.filter([1,-2,3], function(x) { return x > 0; }); //will return [1, 3]

          dojo.lang.unnest

          把指定的參數或數組轉換為一維數組
          Usage Example:
          dojo.lang.unnest(1, 2, 3); //will return [1, 2, 3]
          dojo.lang.unnest(1, [2, [3], [[[4]]]]); //will return [1, 2, 3, 4]

          dojo.lang.toArray

          將輸入轉換為數組
          Usage Example:
          function test()
          {
          return dojo.lang.toArray(arguments, 1);
          }
          test(1,2,3,4,5); //will return [2,3,4,5]

          Dojo入門教程之dojo.io.bind詳解

          dojo.io.bind 處理請求取回需要的數據并處理。
                  
          這個函數是AJAX中最為重要和有用的函數,dojo.io.bind這個類是用來處理客戶端與服務器間通訊的,需要通訊的參數由對象dojo.io.Request所定義,具體通訊的方法則由另外一個對象Transport所提供。Dojo里提供了一個同時兼容IEFirefoxdojo.io.XMLHTTPTransport,但是這個對象位于dojo.io.BrowserIO,因此,一般require dojo.io.IO時,還應該require dojo.io.BrowserIO
          Usage Example: 

          dojo.io.bind(
              url: "http://localhost/test.html", 
          //要請求的頁面地址 
              mimetype: "text/html", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype,默認為 "text/plain" 
              method"GET", //默認為"GET" 
              sync: false//默認為異步執行 
              useCache: false//默認為不使用頁面緩存,注意這里的緩存并不是瀏覽器的緩存,而是Dojo自身所維護的頁面緩存 
              preventCache: false//默認為啟用瀏覽器緩存,否則將通過自動增加不同的參數來確保瀏覽器緩存失效 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 
              load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wante 
              error: function(type, error) { alert(error.message); }, //error is dojo.io.Error 
              timeout: function(type) { alert("請求超時!"); } 
            }
          ); 


           
          你也可以用一個handle來處理所有的事件 

          dojo.io.bind(
              url: "http://localhost/test.html", 
          //要請求的頁面地址 
              mimetype: "text/html", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 
              handle: function(type, data, evt)
                
          if(type == "load") { alert(data); } //data is that we wanted 
                else if (type == "error") { alert(data.message); } //data is the error object 
                else { ; } //other events maybe need handled 
              } 
            }
          );  

            
           
          如果沒有在Request中指定所用的transport,則Dojo會自動的在已注冊的transports中尋找能夠處理這個Requesttransport,如果不能找到,則返回指定的Request。下面是一個指定了transport的例子
            

          dojo.io.bind(
              url: "http://localhost/test.html", 
          //要請求的頁面地址 
              mimetype: "text/html", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 
              transport: "XMLHTTPTransport", 
              load: 
          function(type, data, evt) { alert(data); }, //type should be "load", data is that we wante 
              error: function(type, error) { alert(error.message); }, //error is dojo.io.Error 
              timeout: function(type) { alert("請求超時!"); } 
           }
          ); 


          你還可以利用bind來得到一個Javas cript所定義的對象(注意mimetype必須要定義為"text/javasript" 

          testObj = dojo.io.bind(
              url: "http://localhost/test.js", 
          //test.js里定義了一個對象 
              mimetype: "text/javas cript", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 handle: function(type, data, evt){ 
               if(type == "load") { alert(data); } //data is a object or value 
                else if (type == "error") { alert(data.message); } //data is the error object 
                else { ; } //other events maybe need handled 
              } 
            });   

           
           
          下面是一個Post的例子:    

          dojo.io.bind(
              url: "http://localhost/test.aspx", //
          要提交的頁面地址 
              mimetype: "text/html", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 
              method: "POST", 
              formNode: dojo.byId("myForm"), //
          指定提交的Form名稱 
             load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wanted 
              error: function(type, error) { alert(error.message); }, //error is dojo.io.Error 
              timeout: function(type) { alert("
          請求超時!"); } 
           }
          ); 
            另一個Post的例子(without Form to post): 

          dojo.io.bind(
              url: "http://localhost/test.aspx", 
          //要提交的頁面地址 
              mimetype: "text/html", //請求的頁面的類型,應該設置為與你請求頁面類型對應的mimetype 
              timeoutSeconds: 3000,  //3秒后超時,如果為0則永不超時 
              method: "POST", 
              content: 
          {a: 1, b: 2}, //要提交的數據 
             load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wanted 
              error: function(type, error) { alert(error.message); }, //error is dojo.io.Error 
              timeout: function(type) { alert("請求超時!"); } 
           }
          ); 


            dojo.io.queueBind
           
          有時,我們需要一次發出多個網頁請求,則應該使用dojo.io.queueBind,因為瀏覽器可能只允許同時發出有限個數的請求,如果是使用dojo.io.bind的話,則有可能會申請不到新的XMLHttp對象而導致出錯。
           
          用法與dojo.io.bind是一樣的。
          dojo.io.argsFromMap
           
          用來把對象轉換為URL的參數形式   
          Usage Example:
            dojo.io.argsFromMap({a:1,b:2,c:3}); //will return "c=3&b=2&a=1"
            dojo.io.argsFromMap({name:"
          名稱",value:""},"utf"); //will return "value=?€?&name=????§°", 有中文的話應該指定utf格式,否則dojo.string.encodeAscii返回的編碼是很怪異的
            dojo.io.argsFromMap({a:1,b:2,c:3}, "utf", "c"); //will return "b=2&a=1&c=3"
          ,最后一個參數可以控制指定名稱的值出現在最后
          dojo.io.setIFrameSrc
           
          設置IFrameSrc   
          Usage Example:
            dojo.io.setIFrameSrc(dojo.byId("myFrame"), "http://localhost/test.htm"); //myFrame
          打開指定的網頁
            dojo.io.setIFrameSrc(dojo.byId("myFrame"), "http://localhost/test.htm", true); //myFrame
          打開指定的網頁,并覆蓋瀏覽器的歷史記錄
          模塊:dojo.io.BrowserIO
          基本上就提供了dojo.io.XMLHTTPTransport這個對象
          XMLHTTPTransport
          一般能夠滿足我們的需求,但是其有幾個限制:它不能傳輸文件,不能夠成功執行跨域名的遠程請求,并且不支持 file:// 這樣的協議
          因此,根據應用要求,我們可能會需要選用其它的transport: dojo.io.IframeTransport, dojo.io.repubsubTranport, dojo.io.s criptSrcTransport, ShortBusTransport
          dojo.io.IframeTransport
          ,用法與xmlhttp是一樣的,其優點就是可以跨域,不存在任何的安全問題
          如果Request指定的mimetypetextjavas cript,返回的內容應該是放在第一個textarea里的內容,如果指定的mimetypehtml,則IFrame里的html則是需要的內容。因為瀏覽器兼容的原因,IframeTransport不能正確處理返回類型為XML的請求。 
          關于Rpc,這個類似于Remoting的東西,也將在以后對其進行介紹。


          開始使用dojo
          現在開始使用dojo的第一個函數:dojo.byId
          dojo.byId就等同于常用的document.getElement
          <input type="text" name="username" id="username" value="Mark" />
          <script type="text/javascript">
          var username = dojo.byId('username').value
          alert(username);
          </script>
          OK,是不是和普通的js庫一樣,沒有任何玄機?

          dojo.addOnLoad
          現在我們想在window.onload里面處理一點東西,就像Ext.onReady,這個東西在dojo里叫做dojo.addOnLoad

          Java代碼

          1. dojo.addOnLoad(function(){   
          2.     var username = dojo.byId('username').value   
          3.     alert(username);   
          4. });  

          dojo.connect
          OKwindow.onload搞定了,那么如何監聽普通的dom事件呢?沒問題,強大的dojo.connect出場

          Java代碼

          1. <script type="text/javascript">   
          2. function sayHello(event)   
          3. {   
          4.     alert("Hello");   
          5. }   
          6. dojo.addOnLoad(function(){   
          7.     var btn = dojo.byId('hello');   
          8.     dojo.connect(btn,"onclick",sayHello);   
          9. });   
          10. </script>   
          11. <input type="button" id="hello" value="Hello" /> 
          alert("Hello");
          var btn = dojo.byId('hello');
          dojo.connect(btn,"onclick",sayHello);

          是不是和prototypeEvent.observe($('btnAdd'), "load", doAdd)差不多?
          prototype時最煩的就是那個長長的bindAsListener了,使用dojo.conncect,可以在第三個參數中指定當前的scope

          Java代碼

          1. var name = "Mark"  
          2. function sayHello()   
          3. {   
          4.     alert("Hello " + this.name);   
          5. }   
          6. var obj = {   
          7.     name: "Karl"  
          8. }   
          9. dojo.addOnLoad(function(){   
          10.     var btn = dojo.byId('hello');   
          11.     dojo.connect(btn,"onclick",obj,sayHello);//注意這行的第三個和第四個參數  
          12. });  
          alert("Hello " + this.name);
          name: "Karl"
          var btn = dojo.byId('hello');
          dojo.connect(btn,"onclick",obj,sayHello);//

          OK,點擊按鈕,將輸出:Hello Karl
          這里dojo.connect的第三個參數變成了scope,而handler函數是第四個,實際上
          dojo.connect(btn,"onclick",sayHello);

          dojo.connect(btn,"onclick",null,sayHello);
          相同。
          更加復雜的用法這里不作介紹,寫太多就越搞越復雜了,后面再寫文章詳細介紹dojo.connect,這里只簡單介紹如何綁定DOM事件。

          xmlhttp dojo.xhrGet
          OK,介紹了簡單的DOM操作方法,接下來該到Ajax的傳統項目-XmlHttp
          在使用xmlhttp時,需要注意到編碼的問題,要讓dojo默認綁定為utf-8怎么辦呢?很簡單,只需要修改一下引入dojo.js時的標簽:

          Java代碼

          1. <script type="text/javascript" src="./dojo-lib/dojo/dojo.js" djConfig="isDebug:true,bindEncoding:'UTF-8'"></script>  


          多了一個djConfig屬性,很簡單,第一個isDebug是說是否打開FireBugConsole,第二個是xmlhttp使用的編碼。第二個才是重點,設置了就一勞永逸了。

          這次我們要點擊了hello按鈕后發出一個xmlhttp請求:

          Java代碼

          1. function sayHello() {   
          2.     dojo.xhrGet({   
          3.         url: "http://localhost/hello/sayHello.jsp",   
          4.         handleAs: "text",   
          5.         load: function(responseText)   
          6.         {   
          7.           alert(responseText);   
          8.           dojo.byId("divHello").innerHTML = responseText;   
          9.         },   
          10.         error: function(response)   
          11.         {   
          12.           alert("Error");   
          13.         }   
          14.     });   
          15. }   
          16. dojo.connect(btn,"onclick",sayHello);  
          dojo.xhrGet({
          url: "http://localhost/hello/sayHello.jsp",
          handleAs: "text",
          load: function(responseText)
          {
          alert(responseText);
          dojo.byId("divHello").innerHTML = responseText;
          },
          error: function(response)
          {
          alert("Error");
          }
          });


          看看,夠不夠一目了然?

          url 就是url……
          handleAs 把獲取的內容作為text/html
          load 成功時的回調函數
          error 失敗時的回調函數

          那如果要傳入參數怎么辦?

          Java代碼

          1. var params = {   
          2.     username:'Mark',   
          3.     id:'105'  
          4. }   
          5. dojo.xhrGet({   
          6.     url: "http://localhost/hello/sayHello.jsp",   
          7.     content:params,   
          8.     //...   
          9. });  
          username:'Mark',
          id:'105'
          url: "http://localhost/hello/sayHello.jsp",
          content:params,
          //...

          注意那個content參數,你要傳入的參數是個關聯數組/objectdojo會自動把參數解析出來,要使用post方法?
          dojo.xhrGet ---> dojo.xhrPost
          其他的還有
          dojo.xhrPut
          dojo.xhrDelete

          json
          那要是我想更換獲取到的數據類型,比如jsonxml
          修改handleAs即可,如:
          handleAs: "json"

          Java代碼

          1. dojo.xhrGet({   
          2.     url: "http://localhost/hello/sayHello.jsp",   
          3.     handleAs: "json",   
          4.     load: function(json)   
          5.     {   
          6.         alert(json.name)   
          7.     }   
          8.     //...   
          9. });  
          url: "http://localhost/hello/sayHello.jsp",
          handleAs: "json",
          load: function(json)
          {
          alert(json.name)
          }
          //...

          引用


          handleAs: "json-comment-filtered" 使用注釋符號/**/json數據包含起來,推薦使用
          handleAs: "json-comment-optional" 首先嘗試使用json-comment-filtered,如果執行錯誤,再使用普通的json格式解析
          handleAs: "javascript" dojo嘗試把服務器返回的數據當作javascript執行,并把結果作為參數傳遞給load函數
          handleAs: "xml" xml對象。注意在MozillaIE中的xml是不同的,推薦使用sarissa


          至于jsonobject的轉換等,在http://dojotoolkit.org/book/dojo-book-0-9/part-3-programmatic-dijit-and-dojo/other-miscellaneous-function/converting-json有一個表格,應該能找到你需要的。

          想要直接提交一個表單,就這樣:

          Java代碼

          1. dojo.xhrGet({   
          2.     url: "http://localhost/hello/sayHello.jsp",   
          3.     form: dojo.byId("form1")   
          4.     //...   
          5. });  
          url: "http://localhost/hello/sayHello.jsp",
          form: dojo.byId("form1")
          //...

          要解決IE下那個臭名昭著的緩存問題,就這樣,preventCache會幫你自動生成一個timestamp

          Java代碼

          1. dojo.xhrGet({   
          2.     url: "http://localhost/hello/sayHello.jsp",   
          3.     preventCache: true  
          4.     //...   
          5. });  
          url: "http://localhost/hello/sayHello.jsp",
          preventCache: true
          //...

          dojo.hitch scope/context
          既然用到了xmlhttp,一個常見的問題就是回調函數的scope/context。在prototypemootools里我們常用Function.bind,在dojo中,做相同事情的東西叫做dojo.hitch

          Java代碼

          1. var handler = {   
          2.     name:'Mark',   
          3.     execute1: function(){   
          4.         dojo.xhrGet({   
          5.             url: "http://localhost/hello/sayHello.jsp",   
          6.             handleAs: "text",   
          7.             error: function(text)   
          8.             {   
          9.                 console.dir(this);   
          10.                 alert(this.name);//輸出undefined,這里的this表示當前io參數  
          11.             }   
          12.             //...   
          13.         });   
          14.     },   
          15.     load: function(text){   
          16.         alert(this.name);   
          17.     },   
          18.     execute2: function(){   
          19.         dojo.xhrGet({   
          20.             url: "http://localhost/hello/sayHello.jsp",   
          21.             handleAs: "text",   
          22.             error: dojo.hitch(this,"load") //輸出Mark    
          23.             //error: dojo.hitch(this,this.load); //與上一句相同,知道為什么要用方法名字而不是引用了吧?省去了長長的一串this.xxx   
          24.             //...   
          25.         });   
          26.     }   
          27. }  
          name:'Mark',
          execute1: function(){
          dojo.xhrGet({
          url: "http://localhost/hello/sayHello.jsp",
          handleAs: "text",
          error: function(text)
          {
          console.dir(this);
          alert(this.name);//
          }
          //...
          });
          },
          load: function(text){
          alert(this.name);
          },
          execute2: function(){
          dojo.xhrGet({
          url: "http://localhost/hello/sayHello.jsp",
          handleAs: "text",
          error: dojo.hitch(this,"load") //
          //error: dojo.hitch(this,this.load); //
          //...
          });
          }

          OK,基本的東西解決了,還有很多常用的函數沒有介紹,比如:dojo.querydojo.forEachdojo.marginBoxdojo.contentBox等等
          這個就沒事翻翻dojo.js.uncompressed.js源代碼,dojo的文檔是沒啥好指望的了。

          面向對象,定義Class
          下一步我們看看dojo里如何定義Class

          Java代碼

          1. dojo.declare("Customer",null,{   
          2.     constructor:function(name){   
          3.         this.name = name;   
          4.     },   
          5.     say:function(){   
          6.         alert("Hello " + this.name);   
          7.     },   
          8.     getDiscount:function(){   
          9.         alert("Discount is 1.0");   
          10.     }   
          11. });   
          12.   
          13. var customer1 = new Customer("Mark");   
          14. customer1.say();  
          constructor:function(name){
          this.name = name;
          },
          say:function(){
          alert("Hello " + this.name);
          },
          getDiscount:function(){
          alert("Discount is 1.0");
          }

          declare有三個參數:
          第一個 class名字
          第二個父類的引用
          第三個 ...

          構造函數的名字就叫做"construnctor"

          再來看看如何繼承:

          Java代碼

          1. dojo.declare("VIP",Customer,{   
          2.     getDiscount:function(){   
          3.         alert("Discount is 0.8");   
          4.     }   
          5. });   
          6. var vip = new VIP("Mark");   
          7. vip.say();   
          8. vip.getDiscount();  
          getDiscount:function(){
          alert("Discount is 0.8");
          }

          那么,如何調用父類的方法呢。使用this.inherited方法

          Java代碼

          1. dojo.declare("VIP",Customer,{   
          2.     getDiscount:function(){   
          3.         this.inherited(arguments);   
          4.         //this.inherited("getDiscount",arguments);   
          5.     }   
          6. });  
          getDiscount:function(){
          this.inherited(arguments);
          //this.inherited("getDiscount",arguments);
          }

          關于構造函數:
          父類構造函數總是被自動調用的,所以看下面的例子:

          Java代碼

          1. dojo.declare("Customer",null,{   
          2.     constructor:function(name){   
          3.         this.name = name;   
          4.         alert("base class");   
          5.     },   
          6.     say:function(){   
          7.         alert(this.name);   
          8.     }   
          9. });   
          10.   
          11. dojo.declare("VIP",Customer,{   
          12.     constructor:function(age){   
          13.         this.age = age;   
          14.         alert("child class");   
          15.     },   
          16.     say:function(){   
          17.         alert("name:" + this.name);   
          18.         alert("age:" + this.age);   
          19.     }   
          20. });   
          21.   
          22. var vip = new VIP("123");//1   
          23. vip.say();//2  
          constructor:function(name){
          this.name = name;
          alert("base class");
          },
          say:function(){
          alert(this.name);
          }
          constructor:function(age){
          this.age = age;
          alert("child class");
          },
          say:function(){
          alert("name:" + this.name);
          alert("age:" + this.age);
          }


          1將打印出兩條alert語句,先是父類的構造函數,再是子類的。
          2將輸出"name: 123" "age: 123"
          個人認為,這個特性并不好,因為javascript這種弱類型的語言中,根本無法確定構造函數中的參數是傳遞給誰的,就比如上面的語句執行后,name="123",age="123",那哪個才是正確的?這個問題在使用dojo Gridmodel里就很麻煩,定義一個model得這樣:new dojox.grid._data.Table(null,null,data);我要是想擴展這個Model,更麻煩,所有子類的構造函數都被父類給搞亂了。所以推薦的做法是使用關聯數組作為構造函數的參數,就像Python里的關鍵字參數。

          Java代碼

          1. constructor:function(args){   
          2.     var args = args || {};   
          3.     this.name = args.name;   
          4.     this.age = args.age;   
          5. }  
          var args = args || {};
          this.name = args.name;
          this.age = args.age;

          多繼承,mixin
          說到繼承,多繼承的問題又來了。dojo支持多繼承,準確地說,是mixin。還記得dojo.declare的第二個參數嗎,就是表示父類的那個參數,這個參數可以是一個數組,數組的第一個元素作為聲明的類的父類,其他的作為mixin。子類自動獲得父類和mixin的所有方法,后面的mixin的同名方法覆蓋前面的方法

          Java代碼

          1. dojo.declare("Customer",null,{   
          2.     say:function(){   
          3.         alert("Hello Customer");   
          4.     },   
          5.     getDiscount:function(){   
          6.         alert("Discount in Customer");   
          7.     }   
          8. });   
          9.   
          10. dojo.declare("MixinClass",null,{   
          11.     say:function(){   
          12.         alert("Hello mixin");   
          13.     },   
          14.     foo:function(){   
          15.         alert("foo in MixinClass");   
          16.     }   
          17. });   
          18. dojo.declare("VIP",[Customer,MixinClass],{   
          19. });   
          20. var vip = new VIP();   
          21. vip.getDiscount();   
          22. vip.foo();   
          23. vip.say();//輸出"Hello MixinClass"  
          say:function(){
          alert("Hello Customer");
          },
          getDiscount:function(){
          alert("Discount in Customer");
          }
          say:function(){
          alert("Hello mixin");
          },
          foo:function(){
          alert("foo in MixinClass");
          }



          其他的比較有用的函數就是dojo.mixindojo.extend了,顧名思義,一個是作用于對象實例,一個是用于擴展class,翻文檔和源碼吧。

          package機制
          說完了dojo里的類繼承機制,不得不說說package機制。
          主要用到的有
          dojo.require
          dojo.provide
          dojo.registerModulePath

          dojo.require
          dojo.require就是引入相應路徑文件下的js文件,現在已經有很多library這樣做了。現在我們假設要用
          project/dojo-lib/dojo/string.js

          dojo中的頂層目錄就是dojo.js所在目錄的上一層,"project/dojo-lib/",而dojo.js放在
          project/dojo-lib/dojo/dojo.js
          所以我們就這樣:
          dojo.require("dojo.string");
          比如要引用其他目錄下的:
          project/dojo-lib/dojox/dtl/_base.js,則這樣:dojo.require("dojox.dtl._base");

          project/dojo-lib/dojox/grid/Grid.js dojo.require("dojox.grid.Grid");

          說白了,就和ruby之類的require很相似。

          dojo.provide
          要自己編寫一個package怎么辦,那就利用dojo.provide。比如要寫在:
          project/dojo-lib/com/javaeye/fyting/Package1.js
          那么在對應的Package1.js中第一行需要這樣寫:
          dojo.provide("com.javaeye.fyting.Package1");

          類似java里的package聲明,是吧?

          dojo.registerModulePath
          那要是我寫的js文件不想和dojo放在一起怎么辦呢,那就用registerModulePath。假設要放在:
          project/js/com/javaeye/fyting/Package2.js

          Package2.js和上面的Package1.js一樣的寫法,不需要作特殊變化,就這樣就行:
          dojo.provide("com.javaeye.fyting.Package2");

          在使用時,需要指名這個Package2.js所在的位置,
          dojo.registerModulePath("com","../../js/com");
          只需要注意這里的相對路徑是相對dojo.js來的。

          我們假設所有以com.javaeye開頭的js都放在一起,而com.microsoft的放在另外的地方,為了防止沖突,可以這樣:
          dojo.registerModulePath("com.javaeye","../../js/com/javaeye");
          dojo.registerModulePath("com.microsoft","../../javascript/com/microsoft");

          總得來說,package機制是開發大型項目必須的,但是造成了調試困難,使用dojo.require引入js出錯時,根本不知道是什么原因,所以調試時最好手動引入jsdojotest也是這么搞的。還有js框架中的各種實現類繼承的手法,也造成調試困難,dojo還隨地拋出個Error,又缺少java那樣的error statck,根本不知道錯誤根源在哪兒。所以,期待js原生地支持這些^^
          完整的代碼文件在附件里,一個是含有dojo-1.0.2的,一個是沒有dojo.

          Widgets

          什么是widget呢?一個按鈕,一個圖片,這都是widget,最常見的html widget有鏈接,按鈕,輸入框。

          使用Dojo可以改變widget ,例如在日期輸入框旁邊加上一個彩色日歷,讓用戶可以選擇日期,與此同時Dojo并不會破壞你原始的輸入框,因為Dojo是擴展了你的html而不是替換了它。

          使用widget的優勢主要三點:

          ·             跨平臺:使用Dojo widget,無論使用任何瀏覽器,都會準確的得到正確效果。

          ·             自動退化:一些老瀏覽器可能對javascript支持并不是那么完美,Dojo也可以讓它們顯示出正確的內容,例如前面彩色日歷的例子,如果瀏覽器不支持,那么Dojo會自動將日歷退化到一個簡單的選擇框,或者其他(根據不同widget而定)。

          ·             擴展性:你可以利用Dojo提供的widget創造出新的widget,在這個過程中你并不需要從庫中復制任何代碼或者修改庫中的代碼。

          如何使用Widget

          Widget有很多使用方法。Widget會搜索整個網頁框架,然后自動把應該添加的內容加入到當中。

          下面是個簡單的例子,我們也可以看出WIdget是怎樣自動退化的,因為我們并沒有給ComboBox定義選擇項,而只是一個value,而且所以最后顯示出來的只象是一個簡單的inputbox如果用戶禁用了javascript,顯示結果也會一樣。

          <input dojoType="ComboBox" value="default" dataUrl="comboBoxData.js">

          但是如果我們只想使用W3C標準(譯者注:沒有那些額外的tag,例如dojoType),我們可以用下面的方法。

          <input class="dojo-ComboBox?" value="default" dataUrl="comboBoxData.js">

          <dojo:ComboBox? value="default" dataUrl="comboBoxData.js">

          你可能注意到了dataUrl,他的作用是把comboBoxData.js中的內容加到comboBox中,但是現在comboBoxData.js中沒用任何內容。(譯者注:當然你可以隨意改變dataUrl的內容,名字不是固定的。

          下面是一個select的例子:

          <select dojoType="combobox">
          <option value="foo">foo</option>
          <option value="bar">bar</option>
          <option value="baz">baz</option>
          <option value="thud">thud</option>
          </select>

          從上面的例子中,你知道了很多事情,但卻好像沒什么用處,這里只是想告訴你其實dojo并沒有那么復雜。

          后退和前進

          動態網頁程序(dynamic web application)避免了頻繁的刷新頁面,不過通常也帶來后退和前進按鈕會失去作用。更多的,有的時候,用戶可能很難把網頁加入收藏夾。

          Dojo提供了一個解決辦法,讓網頁程序處理瀏覽器的后退和前進,并且提供給瀏覽器一個唯一的地址。這個解決辦法就是使用dojo.undo.browser

          使用dojo.undo.browser

          dojo 0.2.2版本中,并沒有dojo.undo.browser,這是在0.3以后的版本中才加入的。

          首先,需要使用dojo.undo.browser.setInitialStae(state)設定當瀏覽器第一次載入網頁的狀態。

          理論

          態網頁程序會調用XMLHTTPRequestDOM來更新網頁內容而避免了刷新,更新瀏覽歷史,并且也不會改變瀏覽器的地址欄。這就意味著當用戶點擊了后退按鈕,整個網頁程序丟失了當前運行的狀態(state)。而且即使用戶想把當前的網頁內容加入收藏夾,也是不可能的,因為收藏夾不會記錄網頁程序運行的狀態,而只會簡單的記錄下網頁程序的地址(URL)。

          開發者可以使用dojo.undo.browser包得到用戶點擊后退和前進的事件(event),然后根據這些事件來更新頁面內容。 dojo.undo.browser通過使用一個隱藏的表單(hidden IFRAME)或者一個唯一的標簽(fragment identifier)傳遞瀏覽的歷史記錄。(譯者注:可以想像成一個cookie或者一個session,但是這個session信息是存儲在hidden IFRAME或者標簽中例如:

          http://some.domain.com/my/path/to/page.html#fragmentIdentifier

          譯者注:#fragmentIdentifier就是標簽記錄)

          因為當改變標簽的時候并不會使網頁刷新,所以非常適合記錄當前網頁程序的狀態。當然開發者可以自定義一個更容易讀懂的標簽,并且使用戶可以把它加入收藏夾。

          dojo.undo.browser允許開發者創建一個相對于運行狀態的對象(state object),這個對象會得到回叫(callback)當用戶點擊后退或者前進按鈕。

          開發

          下面是使用dojo.undo.browser之前必須作的一些事情:

          1:在djConfig中設置preventBackButtonFix: false。這樣保證了隱藏的表單(hidden IFRAME)將會添加到頁面當中,如果不加入這段,dojo.undo.browser不會正常工作。

          譯者注:設置方法就是在header中加入如下代碼:

          <script language="JavaScript" type="text/javascript">
          djConfig = { isDebug: true, preventBackButtonFix: false };
          </script>

          2: 加入dojo.require("dojo.undo.browser");

          設定網頁程序的初始狀態:

          dojo.undo.browser.setInitialState(state);

          當用戶每次點擊前進或者后退,state對象都會被調用。

          然后我們需要給state對象創建幾個方法(function

          ·                 得到后退提示:back()backButtion()或者handletypetype可以是“back”或者是“forward”

          ·                 得到前進提示:forward(),forwardButton()或者handle(typetype如上。

          下面是個簡單的例子:

          var state = {
          back: function() { alert("Back was clicked!"); },
          forward: function() { alert("Forward was clicked!"); }
          };

          注冊一個state對象使用下面的方法:

          dojo.undo.browser.addToHistory(state);

          果向改變瀏覽器的地址(URL),引用state對象的changeUrl屬性。如果changeUrltruedojo.undo.browser 就將產生一個唯一的標簽,如果changeUrl被定義為任何其他的值(不包括undefinednull
          posted on 2008-02-19 11:30 Sun River 閱讀(1173) 評論(0)  編輯  收藏
          主站蜘蛛池模板: 马关县| 漾濞| 如东县| 成都市| 渝中区| 德昌县| 保德县| 津市市| 沅陵县| 大足县| 马龙县| 龙川县| 甘肃省| 景东| 岳池县| 中江县| 灵宝市| 大化| 安陆市| 读书| 巴东县| 镇安县| 鸡西市| 荔浦县| 泾源县| 林甸县| 五大连池市| 宜川县| 佛冈县| 静海县| 镇雄县| 辉南县| 永安市| 壤塘县| 万州区| 中方县| 天长市| 辽阳市| 通道| 安龙县| 平谷区|