溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

【翻譯】Ext JS——高效的編碼風格指南

發(fā)布時間:2020-07-20 00:50:12 來源:網(wǎng)絡 閱讀:379 作者:tianxiaode2008 欄目:web開發(fā)

原文:ExtJS - Efficient coding style guide

作者:Raja

  1. 切勿使用“new”關鍵字:在Ext JS中,使用“new”關鍵字來創(chuàng)建一個組件或類的實例是一種錯誤的做法,因為這沒有遵循組件的生命周期。應該使用Ext.create方法來創(chuàng)建對象,例如:

    [javascript] view plaincopy【翻譯】Ext JS——高效的編碼風格指南【翻譯】Ext JS——高效的編碼風格指南

    1. 錯誤: var obj = new Ext.panel.Panel();  

    2.   

    3. 正確: var obj = Ext.create(‘Ext.panel.Panel’);  

  2. 初始化直接量:不要直接創(chuàng)建直接量的對象,例如,使用以下javascript來創(chuàng)建空白對象:

    [javascript] view plaincopy【翻譯】Ext JS——高效的編碼風格指南【翻譯】Ext JS——高效的編碼風格指南


    在javascript中,以上都是創(chuàng)建對象的不正確方式,這是因為如果使用這些處理方式,控制需要去遍歷整個類的層次。因此,作為替代,可以使用以下方式來創(chuàng)建這些類的對象:

    [javascript] view plaincopy【翻譯】Ext JS——高效的編碼風格指南【翻譯】Ext JS——高效的編碼風格指南


    不 過,你接手的可能是別人編寫的遺留代碼,因而會注意到構造函數(shù)的一個“特色”(這或者是另一個不使用它的理由)。“特色”的主要問題是Object的構造 函數(shù)可接受參數(shù),并且它會根據(jù)傳入的值來決定是否將對象的創(chuàng)建委托給另一個內置構造函數(shù),而最終返回的對象可能不是你所預期的,例如:

    [javascript] view plaincopy【翻譯】Ext JS——高效的編碼風格指南【翻譯】Ext JS——高效的編碼風格指南


    1.  // Warning: antipatterns ahead  

    2. // an empty object  

    3. var o = new Object();  

    4. console.log(o.constructor === Object); // true  

    5. // a number object  

    6. var o = new Object(1);  

    7. console.log(o.constructor === Number); // true  

    8.  var stringObj = ‘’;  

    9. var arrayObj = [];  

    10. var obj = {};  

    11.  var stringObj = new String();  

    12. var arrayObj = new Array();  

    13. var obj = new Object();  

  3. 更聰明的使用getCmp: 它將根據(jù)傳遞的id值返回匹配的對象(Ext JS對象)。這是一種快速返回對象的方法。所有對象在創(chuàng)建的時候,都需要使用他們的id作為關鍵字注冊為一個單一對象,這樣,使用 Ext.getCmp(myId)就可以尋找并返回RegistrationObject["myId"],因此,這會變得非常快捷。

    不過,如果都個組件使用了相同的id,它就會失效。在這種情況下,它將會返回最后一個查找到的對象。基于這點,建議盡量不要使用這個來獲取對象。建議的做法是只使用該方法一次,然后將結果保存到一個變量,再在其他地方通過變量來引用對象。

    如果需要為多個組件定義相同的id,建議使用itemId。通過這篇文章可了解id和itemId直接的不同。

  4. 避免不比亞的全局變量: 使用全局變量的主要問題就是它可在javascript應用程序或Web頁面中共享所有代碼。這可能會與使用相同名稱的命名空間引起沖突,在應用程序的兩 個單獨部分定義具有相同名稱但用途不同的全局變量的可能性是存在的。使用不必要的全局變量的第二個缺點是會造成更大的內存損耗,這是因為,對于這些全局變 量,一般情況下是不會進行垃圾回收的,因而不會釋放內存。

  5. 使用var關鍵字來定義全局變量:使用var來定義全局變量與不使用之間的一個細微差別是:能不能使用delete操作符來刪除這些變量。
    使用var來定義的全局變量(包括在函數(shù)內創(chuàng)建的)不能使用delete來刪除,例如:

    [javascript] view plaincopy【翻譯】Ext JS——高效的編碼風格指南【翻譯】Ext JS——高效的編碼風格指南


    1.                  // define three globals  

    2. var global_var = 1;  

    3. global_novar = 2; // antipattern  

    4. (function () {  

    5.                 global_fromfunc = 3; // antipattern  

    6. }());  

    7. // attempt to delete  

    8. delete global_var; // false  

    9. delete global_novar; // true  

    10. delete global_fromfunc; // true  

    11. // test the deletion  

    12. typeof global_var; // "number"  

    13. typeof global_novar; // "undefined"  

    14. typeof global_fromfunc; // "undefined"  

  6. 嘗試去刪除那些未使用的變量和函數(shù):不要保留代碼中那些沒有使用到的變量、函數(shù)或者不必要的注釋,因為這些只會增加文件的大小,從而增加文件的加載時間。

  7. 避免在循環(huán)中創(chuàng)建對象或變量:如果沒有必要,就不要在循環(huán)中創(chuàng)建單一的變量或對象,因為他們的數(shù)量會隨著選好的迭代次數(shù)而增加,進而造成內存泄漏。

  8. 避免過度使用面板: 在大多數(shù)情況下,Ext JS應用程序會受到面板過度使用的影響。無論什么情況都使用面板,或者更準確的說,是無論任何情況下都會使用多個面板。解決辦法就是在使用一些輕量級的替 代品來代替面板。很多人都喜歡面板,不過說實在,在UI的許多部分有點過分了。我曾經看到一個用來顯示幾十個縮略圖的UI,每個圖像都是使用不同面板的 HTML內容來顯示的,而這些面板是完全沒必要的。可以考慮以下替代方法……

  • 是否可以使用Ext.container.Container,而不是Ext.panel.Panel來減少開銷?

  • 是否可以使用數(shù)據(jù)視圖(DataView)來渲染所有數(shù)據(jù)而不是單獨的組件?

  • 是否可以使用自定義的Ext.Component?可以使用不同的配置項來將HTML豬肉到組件:autoEl、html、tpl或數(shù)據(jù)。

  • 是否可使用HTML和CSS,而不是完整的組件?使用Ext.Template或Ext.XTemplate可能更實際。

避免容器嵌套:盡量避免不必要地使用容器,因為每個容器都會創(chuàng)建一個層次結構,并以此為核心來訪問子組件,而這,需要遍歷這些容器的層次結構。因此,要盡量在最小的可能容器數(shù)量下創(chuàng)建視圖。函數(shù)要盡可能?。?每一個函數(shù)都應短小精干和有意義。大的函數(shù)會降低可讀性、可維護性、可重用性和可調試性。除此之外,如果一個對象(非常消耗內存的對象)在函數(shù)開始時進行 實例化,它就會一直存在到函數(shù)結束。所以,如果函數(shù)非常小,那么,它的局部變量、對象等垃圾就可以在更短的時間跨度內被回收,從而釋放內存于其他用途。盡量避免過長的對象引用:應盡量避免大型對象的引用,因為這需要花費更多的時間來遍歷對象的層次結構來獲取所需的組件,例如:[javascript] view plaincopy以上代碼可重寫為以下更有效的方式:[javascript] view plaincopy
  1.  var arrayLength = arrayObj.lenght;  

  2. var obj = Abc.xyz.foo.bar.againFoo.againBar.finalObj;  

  3. forvar I = 0; I < arrayLenght; i++){  

  4.             //pattern  

  5.             If(obj === arrayObj[i]){  

  6.                             Alert(‘pattern code’);  

  7.             }  

  8. }  

  9.   var arrayLength = arrayObj.lenght;  

  10.  forvar I = 0; I < arrayLenght; i++){  

  11.              //anti pattern  

  12.              If(Abc.xyz.foo.bar.againFoo.againBar.finalObj === arrayObj[i]){  

  13.                              Alert(‘Anti pattern code’);  

  14.              }  

  15. }  

應避免吊裝(hoisting)問題:javascript 允許在一個函數(shù)內任何個地方使用多個var語句,而他們的行為與在函數(shù)頂部定義變量是沒有區(qū)別的,這種行為通常被稱為吊裝。在使用變量之后再在函數(shù)內進行 聲明,可能會導致邏輯錯誤。對于javascript來說,只要變量在同一作用域(同一函數(shù))被使用,它就會被聲明,無論是否使用了var來定義,例如:[javascript] view plaincopy第一個alert將會顯示“underfined”,這是因為myname被認為是在函數(shù)內部的局部變量(盡管是在之后聲明的)。所以變量的定義都會被吊裝到函數(shù)頂部。因此,要避免這種混亂,最好的方式就是在前期聲明所有打算使用到的變量。
  1. // antipattern  

  2. myname = "global"// global variable  

  3. function func() {  

  4.        alert(myname); // "undefined"  

  5.        var myname = "local";  

  6.        alert(myname); // "local"  

  7. }  

  8. func();  

創(chuàng)建高效的for循環(huán):使用for循環(huán)來遍歷javascript集合,應將集合的長度緩存到一個變量,并使用改變量作為for循環(huán)的條件,例如:[javascript] view plaincopy
  1.   for (var i = 0; i < myarray.length; i++) { //antipattern use of collection length  

  2.       // do something with myarray  

  3.  }  

  4.   

  5. //Right pattern  

  6. var arrLength =  myarray.length;  

  7. for (var i = 0; i < arrLength; i++) {  

  8.      // do something with myarray  

  9. }  

使用hasOwnProperty:在遍歷對象的屬性的時候,使用hasOwnProperty方法來過濾原型鏈屬性是相當重要的,例如:[javascript] view plaincopy在定義了man之前,對象原型添加了一個有用的名為clone的方法。原型鏈的存在意味著所以對象都會自動獲得該新方法。為了避免在枚舉man的時候顯示clone方法,就需要調用hasOwnProperty方法來過濾原型方法,例如:[javascript] view plaincopy
  1. // 1.  

  2.    // for-in loop  

  3.    for (var i in man) {  

  4.           if (man.hasOwnProperty(i)) { // filter  

  5.                  console.log(i, ":", man[i]);  

  6.           }  

  7.     }  

  8.     /* 

  9.        result in the console 

  10.        hands : 2, legs : 2, heads : 1 

  11.     */  

  12.     // 2.  

  13.    // antipattern:  

  14.   // for-in loop without checking hasOwnProperty()  

  15.    for (var i in man) {  

  16.         console.log(i, ":", man[i]);  

  17.    }  

  18.   /* 

  19.    result in the console 

  20.    hands : 2, legs : 2, heads : 1, clone: function() 

  21.  */  

  22.   var man = {hands: 2, legs: 2, head: 1};  

  23.  //somewhere else in the code  

  24. // a method was added to all object  

  25. If( typeof Object.prototype.clone === undefined){  

  26.         Object.prototype.clone = function(){};  

  27. }  

使用===代替==:javascript 在比較隱式類型變量的時候,會進行類型轉換,而這也就是為什么在比較“false== 0”或“"" == 0”時返回true的原因。為了避免因隱式類型轉換所造成的混亂,在比對值與不同的類型表達式的時候,應始終使用===或!==操作符來進行檢查。[javascript] view plaincopy另一學派的觀點是,當使用==已經足矣的時候,使用===就顯得有掉多余,例如,當使用typeof的時候,明確返回的是字符串,這時候就沒必要使用恒等。不過JSLint要求嚴格的相等,它要求代碼保持一致的外觀以及減少閱讀代碼的精力(這個==是故意還是遺漏?)。
  1.  var zero = 0;  

  2. if (zero === false) {  

  3.       // not executing because zero is 0, not false  

  4. }  

  5. // antipattern  

  6. if (zero == false) {  

  7.       // this block is executed...  

  8. }  

不要使用eval:一定要記住“eval是魔鬼”這句口頭禪。這個函數(shù)可接受任意的字符串,并將字符串作為javascript代碼執(zhí)行,例如:[javascript] view plaincopy因此,在這里使用eval會將un定義為一個數(shù)字直接量。假如把jsstrig的值作為用戶的輸入值,這將會導致不少的安全問題。所以,使用eval會帶來安全隱患。
  1.  console.log(typeof un); // "undefined"  

  2. var jsstring = "var un = 1; console.log(un);";  

  3. eval(jsstring); // logs "1"  

  4. console.log(typeof un); // "number"  

parseInt的正確用法:正確使用parseInt的redix可以避免一些不必要的結果,例如:[javascript] view plaincopy因此,要永遠記住使用第二個變量,即redix,來定義數(shù)字的類型,無論它是十進制、八進制還是十六進制。
  1.  alert(parseInt("8")); // "Will print 8"  

  2. alert(parseInt("08")); // "Will print 0"  

  3. alert(parseInt("08,10")); // "Will print 8"  

  4. If we use parseInt(“08”), it gives octal value of 08.  

小心函數(shù)吊裝:該問題類似于上面討論的變量吊裝。他們唯一的區(qū)別是只在使用函數(shù)聲明才會發(fā)生,而不是匿名函數(shù)。函數(shù)聲明這種情況,函數(shù)聲明被吊裝時,不單只是聲明問題,處理不當就會出現(xiàn)一些非預想的結果,例如:[javascript] view plaincopy在 示例中,會看到就像普通變量一樣,無論foo或bar自身位于hoistMe的任何地方,都會將他們移動到頂部,重寫全局的foo和bar。不同的地方是 本地(local)的foo定義被吊裝到頂部并能正常工作,盡管它是在后面定義的。而bar的定義則不會被吊裝,只是進行了聲明。這就是為什么直到代碼執(zhí) 行到bar的定義,會發(fā)現(xiàn)它是undefined且不能作為函數(shù)使用(同時阻止了全局的bar出現(xiàn)在作用域鏈中)。
  1.  // antipattern  

  2. // for illustration only  

  3. // global functions  

  4. function foo() {  

  5. alert('global foo');  

  6. }  

  7. function bar() {  

  8. alert('global bar');  

  9. }  

  10. function hoistMe() {  

  11. console.log(typeof foo); // "function"  

  12. console.log(typeof bar); // "undefined"  

  13. foo(); // "local foo"  

  14. bar(); // TypeError: bar is not a function  

  15. // function declaration:  

  16. // variable 'foo' and its implementation both get hoisted  

  17. function foo() {  

  18. alert('local foo');  

  19. }  

  20. // function expression:  

  21. // only variable 'bar' gets hoisted  

  22. // not the implementation  

  23. var bar = function () {  

  24. alert('local bar');  

  25. };  

  26. }  

  27. hoistMe();  

將屬性添加到全局命名空間:在將一個屬性添加到全局命名空間或全局對象的時候,要小心,或許這已經存在了,可能會覆蓋掉他們。因此,在添加一個屬性或創(chuàng)建命名空間之前,最好先檢查一下它是否存在,例如:[javascript] view plaincopy為了避免在全局命名空間創(chuàng)建任何成員時編寫這些樣板代碼,可以創(chuàng)建一些可重用的代碼,將要創(chuàng)建的對象傳遞過去,讓代碼去執(zhí)行上述驗證并決定添加或放棄對象。
  1.  // unsafe and antipattern  

  2. var MYAPP = {};  

  3. // better  

  4. if (typeof MYAPP === "undefined") {  

  5. var MYAPP = {};  

  6. }  

  7. // or shorter  

  8. var MYAPP = MYAPP || {};  

利用JSLint:JSLint 會獲取javascript源代碼并掃描他們。如果發(fā)現(xiàn)問題,它會返回問題描述和大致位置的消息。問題不一定是語法錯誤,盡管經常會是。JSLint專注 于一些風格約定和結構問題。這并不能說明你的程序是正確,只是提供一些方式來協(xié)助發(fā)現(xiàn)問題。只需要簡單的粘貼腳本,它就可以快速的掃描代碼并找出任何明顯 的問題和錯誤。網(wǎng)址:http://www.jslint.com/避免使用with語句:乍看上去,With語句看上去不賴,主要原因是它可以提供一種簡單方式來訪問嵌套很深的對象,例如:[javascript] view plaincopy代替:[javascript] view plaincopy不幸的是,經過一些測試后,會發(fā)現(xiàn)他們在設置新成員時的表現(xiàn)非常糟糕,替代方法是,可以使用var:[javascript] view plaincopy
  1.                   var o = being.person.man.bodyparts;    

  2.                 o.arms = true;    

  3. o.legs = true;  

  4. being.person.man.bodyparts.arms = true;    

  5.                being.person.man.bodyparts.legs= true;  

  6. with (being.person.man.bodyparts) {    

  7.                                arms = true;    

  8.                                legs = true;    

  9.                 }  

使用Ext JS內部函數(shù)來添加或移除Ext JS組件的元素:要將一些對象添加到Ext JS容易,不建議使用以下代碼:[javascript] view plaincopy以上代碼的問題:如果使用以上代碼將一些東西添加到容易,Ext JS的所有內部任務就不會在將對象添加到容器時執(zhí)行,而這將會引起一些問題。解決:應使用容器的add方法,或使用組件其他類似的內部函數(shù)來處理。
  1. componentObj.items.items[0] = newObject;  

從Ext JS的組件中返回組件:要從Ext JS的組件中返回對象,不要使用以下代碼:[javascript] view plaincopy問題:如果在上述層次結構加入了一個新的層,如一個面板或容器,那么整個層次結構就會變得不穩(wěn)定,可能會返回錯誤的結果。解決:使用Ext.getCmp或queryById來代替過長的層級遍歷。盡管這比層級遍歷要慢,但可保證不會出現(xiàn)以上所說層次問題。(譯者注:在4中,可使用down或up方法查詢子組件或父組件)
  1. var anObj = componentObject.items.items[0].items.items[1];  

編寫可讀、可調試和可重用的代碼:在編寫代碼時,開發(fā)人員應創(chuàng)建短小且有意義的類或函數(shù)。不要試圖去把大量的代碼寫在一個單獨的塊中。盡量保持代碼塊短小,從而讓它跟易于重復使用,且更易于閱讀。使用get/set方法: 如果使用config配置項來定義類的變量,Ext JS會自動創(chuàng)建變量的修改方法(setter)和訪問方法(getter),使用這些修改方法和訪問方法可提供代碼的可讀性。如果使用這些方法來而不是直 接使用變量名,還可以重寫這些方法或為這些方法添加功能。因此,應盡可能使用訪問方法和修改方法作為類這層的變量并使用他們。永遠不要使用自動布局來創(chuàng)建組件:一些常見的錯誤就是因為Ext JS開發(fā)人員在創(chuàng)建容器的時候忘記為他們定義布局了。盡管這在一些瀏覽器上或特定版本的瀏覽器會運行得很好,但從長遠來看,這會導致某些部件出現(xiàn)黑屏或失真等問題,例如:[javascript] view plaincopy在這里,在面板中沒有定義布局,面板的高度和寬度將不會根據(jù)它的組件的flex值進行分配。原因就是容器的布局不知道如何將容器的高度和寬度分配給容器的組件。如果把“l(fā)ayout:hbox”的注釋去掉,這兩個按鈕將會根據(jù)父容器調整寬帶和高度。
  1.  Ext.create(‘Ext.panel.Panel’,{  

  2.                 height: 200,  

  3.                 width: 500,  

  4.                 //layout: ‘hbox’,          // anti pattern if layout is not defined  

  5.                 items:[  

  6.                                 {  

  7.                                                 xtype: ‘button’,  

  8.                                                 id: ‘button1’  

  9.                                                 flex: 1  

  10. },{  

  11.                                                 xtype: ‘button’,  

  12.                                                 id: ‘button2’  

  13.                                                 flex: 1  

  14. }  

  15. ]  

  16. });  

避免使用固定的高度和寬度: 千萬不要在應用程序中固定任何容器或組件的高度和寬度,因為這會破壞應用程序的布局流動性。盡量將最頂層的容器或viewport的高度和寬度定義為屏幕 大小,然后小心的通過正確的使用flex或布局將這個尺寸分分派給子組件或子容器,不要使用硬編碼的高度或寬度,也可以通過使用Ext JS的功能來計算,如Ext.getBody().getViewSize().height或Ext..getBody().width:[javascript] view plaincopy
  1. Ext.create(“Ext.panel.Panel”,{  

  2.                height: Ext.getBody().getViewSize().height,  

  3.                width: Ext.getBody().getViewSize().width  

  4. );  

正確使用flex關鍵字:flex 是一個用來保持流動性布局的非常重要的關鍵字,該值通常用來決定如何接收父容器的尺寸,例如,如果兩個組件的定義分別為flex=1和flex=2,那 么,這兩個組件從父容器接收到的尺寸比例就是1:2。在這里,還需要留意另一個重點,就是該值只用來劃分父容器的寬度或高度,而不能同時來決定子組件的寬 度和高度,例如:[javascript] view plaincopy以 上代碼,使用了水平盒子布局,因而,只有按鈕的寬度會根據(jù)flex值的比例進行劃分,而兩個按鈕的高度則會是100%,即是每個按鈕的寬度會是250,而 高度是200。同樣,如果將面板的布局修改為垂直盒子布局,那么,每一個按鈕的寬度將會是500,而高度會是100。因此,要適當并謹慎地使用flex來 實現(xiàn)更好的流動布局。
  1.  Ext.create(‘Ext.panel.Panel’,{  

  2.                 height: 200,  

  3.                 width: 500,  

  4.                 layout: ‘hbox’,           

  5.                 items:[  

  6.                                 {  

  7.                                                 xtype: ‘button’,  

  8.                                                 id: ‘button1’  

  9.                                                 flex: 1  

  10. },{  

  11.                                                 xtype: ‘button’,  

  12.                                                 id: ‘button2’  

  13.                                                 flex: 1  

  14. }  

  15. ]  

  16. });  

盡量少用minxWidth、maxWidth、minHeight和maxHeight:盡量在需要的時候才使用這些屬性,否則就不要使用他們,因為在組件布局方面,他們的使用是非常昂貴的。如果在組件中碰到這些屬性,布局會重新進行計算,因此,這樣的代價非常昂貴。使用Sencha Cmd工具來壓縮(minification)代碼: 進行壓縮處理時,會消除空白、注釋和javascript代碼中其他不重要的部分,這樣可減少javascript文件的大小,從而減小服務器到瀏覽器的 傳輸量。另外,壓縮處理還會重命名變量為較短的名稱(但只有在它是安全的時候),如前面代碼中的參數(shù)D、C、B或A。壓縮處理只會重命名局部變量,因為重 命名全局變量可能破壞代碼。這也是為什么使用局部變量是一個好做法的主要愿意。如果在一個函數(shù)內,使用全局變量,如DOM引用,超過一到兩次,那就給它分 配一個局部變量,這是好的做法。這些通常需要一些工具(壓縮)來實現(xiàn),如Ext JS命令行工具(只適用于Ext JS的應用程序開發(fā))、雅虎的YUICompressor或谷歌的Closure Complier(適用于普通的javascript應用程序),這喲這樣加快頁面加載時間。壓縮為生產準備的腳本是十分重要的,因為最終可以將文件的大 小大大壓縮,通??梢詨嚎s一半的大小。保持DOM的輕量化:盡量保持DOM的輕量 化可加快DOM的訪問和維護速度。這可通過移除不必要的DOM元素來實現(xiàn),例如,如果使用卡片布局,且每個卡片都要顯示大量容器或組件,而且用戶不會返回 之前的卡片,最好的方式就是在程序(這樣所需的容器或組件就不會再次創(chuàng)建)中緩存DOM元素,然后將DOM元素從DOM中移除以讓它輕量化。盡量減少DOM訪問:DOM訪問是昂貴的,它是javascript性能最常見的瓶頸。這是因為DOM的實現(xiàn)通常是與javascript引擎分離的。底線就是應將DOM訪問減少到最低限度,這意味著:
  • 盡量使用Ext JS的方法來訪問或維護DOM,以獲得跨瀏覽器支持,否則某些代碼在某些瀏覽器可能會失敗,這是因為每個瀏覽器都有它自己的DOM訪問方式。

  • 當要遍歷HTML集合時,緩存集合的長度

  • 在可能的情況下,使用API的選擇器

  • 將DOM引用指派給局部變量并使用舉報變量進行操作

  • 避免在循環(huán)中進行DOM訪問

不要創(chuàng)建內聯(lián)處理函數(shù):千萬必要創(chuàng)建內聯(lián)函數(shù),因為對于回調會監(jiān)聽所使用的函數(shù)來說,是常見的問題源。他們不單需要花費時間來創(chuàng)建,還需要昂貴的閉包,例如:[javascript] view plaincopy以上代碼,每當構造函數(shù)執(zhí)行一次,就會創(chuàng)建一個新的監(jiān)聽函數(shù),這不單需要花費時間處理閉包問題,還潛在內存泄漏問題。以下是首選的模式:[javascript] view plaincopy在以上代碼中,監(jiān)聽函數(shù)只會創(chuàng)建一次并保存在類中。每個實例都會共享相同的函數(shù)。創(chuàng)建函數(shù)的開銷只有一次,而且沒有閉包泄漏的風險。更重要的是,這樣的編碼風格,還可以讓子類輕松的去重寫監(jiān)聽。
  1.  Ext.define(‘MyClass’,{  

  2.                 constructor: function(config){  

  3.                                 this.store.on(‘load’, this.onStoreLoad, this);  

  4.                 },  

  5.                 onStoreLoad: function(){  

  6.                                 ………;  

  7. }  

  8. });  

  9.  Ext.define(‘MyClass’,{  

  10.                 constructor: function(config){  

  11.                                 this.store.on(‘load’, function(){  

  12.                 ………..;  

  13. }, this);  

  14.                 }  

  15. });  

正確使用xtype:一個常見的神話就是xtype可通過延遲初始化提高性能。通常,這不是真的。盡管通過xtype配置項將組件添加到容器,它還是進行實例化,盡管它還不可見。雖然xtype有很大用途,但對于應用程序的性能或資源消耗來說沒有實際可衡量的影響。千萬不要使用整個ext-all.js庫: 通常,ext-all.js是包含了全部功能和組件的巨大編碼集,但我們很少會使用到Ext JS的全部功能和組件,因此,沒必要在只使用了60%到70%代碼的時候去加載一個巨大的文件。可以使用Sencha命令行工具來壓縮生產代碼,它會從 ext-all.js中復制所需的類并粘貼到結果all-classes.js。如果沒有使用Sencha命令行工具,還可以通過其他方式來確保不用加載 整4個ext-all.js文件。批處理任務:盡量使用批處理進行更新,以便渲染只在最后時刻觸發(fā)一次渲染。例如,修改記錄的字段值會立即更新到網(wǎng)格,如果想讓幾個字段的更新更高效,就進行批處理,例如:[javascript] view plaincopy如果要修改的字段更多,效果會更明顯。另一個例子是將組件添加到容器,每添加一次,容器就會重新計算布局一次。將多個組件傳遞給同一個add方法,將會高效得多,例如:[javascript] view plaincopy在沒有其他批處理機制的時候,可以使用暫停布局來臨時輔助實現(xiàn):[javascript] view plaincopy
  1.  container.suspendLayout = true;  

  2. doSomethingToChangeLotsOfLayoutChange();  

  3. container.suspendLayout = false;  

  4. container.doLayout();  

  5.  //slow code  

  6. container.add(panel);  

  7. container.add(button);  

  8. container.add(grid);  

  9.   

  10. //fast  

  11. container.add(panel, button, grid);  

  12.   

  13. //using an array is also fast  

  14. container.add([panel, button, grid]);  

  15.  record.beginEdit();  

  16. record.set(‘name’, ‘Tom’);  

  17. record.set(‘age’, 17);  

  18. record.set(‘member’, true);  

  19. record.endEdit();  

使用deferredRender: 在使用卡片布局或標簽面板的時候,要認真考慮一下deferredRender選項。當將它設置為true,就可以將隱藏的條目或選項卡實現(xiàn)延遲渲染。只 有在隱藏的條目第一次顯示的時候,才會進行渲染。當設置為false,所以的卡片或標簽就會作為容器渲染的一部分在同一時間進行渲染。延遲渲染通常來說挺好的,這有助于將渲染過程分解為較小的數(shù)據(jù)塊,不會對用戶造成明顯的延遲。不過,渲染所有的卡片或標簽頁,在隱藏的卡片或標簽頁第一次顯示的時候有助于改善UI的響應。網(wǎng)格的緩沖渲染:在使用網(wǎng)格的時候,如果數(shù)據(jù)集很打,使用緩沖渲染吧。這意味著在加載存儲的時候,存儲要維持一個“預讀”緩沖,以保存將要使用到的記錄頁。如果數(shù)據(jù)少于100000行(也取決于每行的列數(shù)),最好的方式是在客戶端將所有數(shù)據(jù)保存到預讀緩沖區(qū)。渲染大的HTML表格會謀殺性能。這事實上只是HTML表格算法,只保持所以數(shù)據(jù)應該不會導致問題。要做的只是滾動的時候,在“適當時候”渲染表格的行。要做到這一點,只需要一次加載預讀緩沖中的所有數(shù)據(jù)。這樣做后,就可以從預讀緩存中加載存儲的主要數(shù)據(jù),例如:[javascript] view plaincopy預 讀所有所預期的數(shù)據(jù)集后,回調會加載存儲的主緩存(映射到網(wǎng)格面板內的緩存)所使用的50行數(shù)據(jù)。由于只能得到小于50行的表格,所以在滾動接近視圖邊界 的時候,它就會更新。該技術在4.0.x工作OK,不過在4.1.0進行了翻修,變得更快和更平滑。在網(wǎng)格目錄的緩沖網(wǎng)格示例延時該技術。要注意的是,太多的列會對HTML的性能產生影響。元素太多也會這樣,因而需要避免顯示不需要的列。
  1.  myStore = ……{  

  2. ………….,  

  3. Buffered: true// Tell grid to use a paging scroll manager to scroll and refresh table automatically.  

  4.                                 perPageCount: 0 // never remove pages from the prefetch buffer;  

  5. }  

  6.   

  7. myStore.prefetch({  

  8.                                 start: 0,  

  9.                                 limit: 999999,  

  10.                                 callback: function(){  

  11.                                 myStore.load(0, 49);  

  12. }  

  13. });  

在標簽面板的每個標簽頁的beforeRender事件處理中填充標簽頁: 在beforeRendere中填充標簽頁是更好的方法。正確的實現(xiàn)這個可以有效的改進包含大量未渲染組件的應用程序的性能。雖然實例化一個組件的時間比 渲染或布局所需要的時間要小,但如果有大量的未渲染組件也需要時間。帶有許多標簽頁的標簽面板這樣處理會更理想。要特別支出的是,我建議的只是 shuffle time around:cut the time taken for the initial load in favour of slightly slower tab transitions.這只是你武器庫中的另一種技術。與以往一樣,優(yōu)化的黃金規(guī)則是在實現(xiàn)之前,要做一些有意義的測量。使用mon代替on:這兩個關鍵字都是用來事件處理綁定到事件的。不過,使用mon而不是on會更高效,因為這可確保監(jiān)聽會在MyClass的實例被銷毀的時候自動移除它,例如:[javascript] view plaincopy
  1.  Ext.define(‘MyClass’,{  

  2.                                 Constructor: function(config){  

  3.                                                 //this.store.on(‘load’, this.onStoreLoad, this); // this is not good  

  4.                                                 this.store.mon(‘load’, this.onStoreLoad, this);  

  5.                                 },  

  6.                                 onStoreLoad: function(){  

  7.                                                 ………;  

  8. }  

  9.   

  10. });  

在事件處理程序中不要保留對this的引用: 通常,在任何Ext JS組件的內聯(lián)事件處理函數(shù)工作時,都需要使用this關鍵字來獲取相應類的對象的應用。通常情況下,組件的事件處理程序的this指向的是該組件這個對 象。隱藏,要解決這個問題,一些開發(fā)人員會在構造函數(shù)或類的initComponent方法內使用一些全局變量來引用類,然后在內聯(lián)處理中使用全局變量來 獲取相應的類對象,不過,這是錯誤的做法,我們贏遵循這里的約定。嘗試使用客戶端緩存: 本地存儲、session存儲、sqllite等等。如果使用HTML5,就可以將一些數(shù)據(jù)保持在客戶端(不是cookie),并在再次瀏覽該頁時使用這 些數(shù)據(jù)。這樣,就可以避免將一些沒必要的東西發(fā)送到服務器或數(shù)據(jù)庫。在Ext JS,可以使用代理來處理這類緩存。在Ext JS中有兩類代理:ClientProxy和ServerProxy。ClientProxy就是用來處理客戶端緩存的。有以下三種類型的 ClientProxy:除了這些,一些瀏覽器,如chrome,還支持一些特殊類型的客戶端數(shù)據(jù),如SQLLite,它可以在客戶端存儲一些數(shù)據(jù)。因此,通過使用這些技術,可以用來提高應用程序的性能。
  • Ext.data.proxy.MemoryProxy:MemoryProxy是一個輔助性的代理。通常,它用來加載一些內聯(lián)數(shù)據(jù)到存儲。MemoryProxy的內容會在頁面刷新后對視。它通常用來加載臨時數(shù)據(jù)。

  • Ext.data.proxy.SessionStorage:SessionStorageProxy 使用的是新的HTML5的SessionStorage API來加載和保持數(shù)據(jù)到客戶端瀏覽器。SessionStorage設置的字段是基于窗口的,這意味著瀏覽器關閉后,數(shù)據(jù)也會丟失,即使網(wǎng)站在另一個瀏 覽器窗口依然是打開的。SessionStorage的數(shù)據(jù)被局限于創(chuàng)建他的瀏覽器窗口中。

  • Ext.data.proxy.LocalStorage:LocalStorageProxy 使用新的HTML5的localStorage來加載和保存數(shù)據(jù)到客戶端瀏覽器。LocalStorage可在域中設置字段,這意味著關閉瀏覽器后再打開 它,數(shù)據(jù)還在LocalStorage中。LocalStorage允許長期存儲,此外還可以在所有瀏覽器的標簽頁或窗口中訪問它。

不要使用Array.isArray:Array.isArray(anyObject) 方法用來判斷anyObject是否一個數(shù)組對象。該方法只能在Chrome中工作,不能在IE中工作。IE并不能識別該方法并會給出錯誤。可使用 instanceof來替代該方法來達到相同的目的。instanceof方法既可在IE工作,也可在Chrome工作。一定要注意日期格式:在解析日期的時候,要注意日期字符串的格式是否既支持IE,又支持chrom:[javascript] view plaincopy不要使用var dateString = "Oct/02/2011",IE不支持,在chrome中是支持的。我已經在應用程序修正了這個。
  1.  var dateString = "03/20/2008";                                   

  2. var dateString = "2008/03/20";                                                   

  3. var dateString = "03-20-2008";                                    

  4. var dateString = "March 20, 2008";                                           

  5. var dateString = "Mar 20, 2008";                                                

  6. var dateString = "Oct 2, 2011";  

別忘了以下要點:以下是在將代碼發(fā)布為產品時不應忘記的一些要點:沒有尾隨逗號即使只有一行注釋,也要使用多行注釋來代替單行注釋沒有調試的代碼要留下注釋在預期的情況下,不要丟失任何分號不要在生產代碼中使用console.log


作者會持續(xù)更新這篇文章。如果你有任何意見會反饋,可聯(lián)系作者。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI