1,切勿使用“new”關(guān)鍵字:在Ext JS中,使用“new”關(guān)鍵字來創(chuàng)建一個組件或類的實例是一種錯誤的做法,因為這沒有遵循組件的生命周期。應(yīng)該使用Ext.create方法來創(chuàng)建對象,例如: 1. 錯誤: var obj = new Ext.panel.Panel(); 2. 3. 正確: var obj = Ext.create(‘Ext.panel.Panel’); 2,初始化直接量:不要直接創(chuàng)建直接量的對象,例如,使用以下javascript來創(chuàng)建空白對象: 1. var stringObj = new String(); 2. var arrayObj = new Array(); 3. var obj = new Object(); 在javascript中,以上都是創(chuàng)建對象的不正確方式,這是因為如果使用這些處理方式,控制需要去遍歷整個類的層次。因此,作為替代,可以使用以下方式來創(chuàng)建這些類的對象: 1. var stringObj = ‘’; 2. var arrayObj = []; 3. var obj = {}; 不過,你接手的可能是別人編寫的遺留代碼,因而會注意到構(gòu)造函數(shù)的一個“特色”(這或者是另一個不使用它的理由)。“特色”的主要問題是Object的構(gòu)造函數(shù)可接受參數(shù),并且它會根據(jù)傳入的值來決定是否將對象的創(chuàng)建委托給另一個內(nèi)置構(gòu)造函數(shù),而最終返回的對象可能不是你所預(yù)期的,例如: 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 3,更聰明的使用getCmp:它將根據(jù)傳遞的id值返回匹配的對象(Ext JS對象)。這是一種快速返回對象的方法。所有對象在創(chuàng)建的時候,都需要使用他們的id作為關(guān)鍵字注冊為一個單一對象,這樣,使用Ext.getCmp(myId)就可以尋找并返回RegistrationObject["myId"],因此,這會變得非??旖?。 不過,如果都個組件使用了相同的id,它就會失效。在這種情況下,它將會返回最后一個查找到的對象?;谶@點,建議盡量不要使用這個來獲取對象。建議的做法是只使用該方法一次,然后將結(jié)果保存到一個變量,再在其他地方通過變量來引用對象。 如果需要為多個組件定義相同的id,建議使用itemId。通過這篇文章可了解id和itemId直接的不同。 4,避免不比亞的全局變量:使用全局變量的主要問題就是它可在javascript應(yīng)用程序或Web頁面中共享所有代碼。這可能會與使用相同名稱的命名空間引起沖突,在應(yīng)用程序的兩個單獨部分定義具有相同名稱但用途不同的全局變量的可能性是存在的。使用不必要的全局變量的第二個缺點是會造成更大的內(nèi)存損耗,這是因為,對于這些全局變量,一般情況下是不會進行垃圾回收的,因而不會釋放內(nèi)存。 5,使用var關(guān)鍵字來定義全局變量:使用var來定義全局變量與不使用之間的一個細微差別是:能不能使用delete操作符來刪除這些變量。 01. // define three globals 02. var global_var = 1; 03. global_novar = 2; // antipattern 04. ( function () { 05. global_fromfunc = 3; // antipattern 06. }()); 07. // attempt to delete 08. delete global_var; // false 09. 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)建單一的變量或?qū)ο?,因為他們的?shù)量會隨著選好的迭代次數(shù)而增加,進而造成內(nèi)存泄漏。 8,避免過度使用面板:在大多數(shù)情況下,Ext JS應(yīng)用程序會受到面板過度使用的影響。無論什么情況都使用面板,或者更準確的說,是無論任何情況下都會使用多個面板。解決辦法就是在使用一些輕量級的替代品來代替面板。很多人都喜歡面板,不過說實在,在UI的許多部分有點過分了。我曾經(jīng)看到一個用來顯示幾十個縮略圖的UI,每個圖像都是使用不同面板的HTML內(nèi)容來顯示的,而這些面板是完全沒必要的??梢钥紤]以下替代方法……
9,避免容器嵌套:盡量避免不必要地使用容器,因為每個容器都會創(chuàng)建一個層次結(jié)構(gòu),并以此為核心來訪問子組件,而這,需要遍歷這些容器的層次結(jié)構(gòu)。因此,要盡量在最小的可能容器數(shù)量下創(chuàng)建視圖。 10,函數(shù)要盡可能小:每一個函數(shù)都應(yīng)短小精干和有意義。大的函數(shù)會降低可讀性、可維護性、可重用性和可調(diào)試性。除此之外,如果一個對象(非常消耗內(nèi)存的對象)在函數(shù)開始時進行實例化,它就會一直存在到函數(shù)結(jié)束。所以,如果函數(shù)非常小,那么,它的局部變量、對象等垃圾就可以在更短的時間跨度內(nèi)被回收,從而釋放內(nèi)存于其他用途。 11,盡量避免過長的對象引用:應(yīng)盡量避免大型對象的引用,因為這需要花費更多的時間來遍歷對象的層次結(jié)構(gòu)來獲取所需的組件,例如: 1. var arrayLength = arrayObj.lenght; 2. for ( var I = 0; I < arrayLenght; i++){ 3. //anti pattern 4. If(Abc.xyz.foo.bar.againFoo.againBar.finalObj === arrayObj[i]){ 5. Alert(‘Anti pattern code’); 6. } 7. } 以上代碼可重寫為以下更有效的方式: 1. var arrayLength = arrayObj.lenght; 2. var obj = Abc.xyz.foo.bar.againFoo.againBar.finalObj; 3. for ( var I = 0; I < arrayLenght; i++){ 4. //pattern 5. If(obj === arrayObj[i]){ 6. Alert(‘pattern code’); 7. } 8. } 12,應(yīng)避免吊裝(hoisting)問題:javascript允許在一個函數(shù)內(nèi)任何個地方使用多個var語句,而他們的行為與在函數(shù)頂部定義變量是沒有區(qū)別的,這種行為通常被稱為吊裝。在使用變量之后再在函數(shù)內(nèi)進行聲明,可能會導(dǎo)致邏輯錯誤。對于javascript來說,只要變量在同一作用域(同一函數(shù))被使用,它就會被聲明,無論是否使用了var來定義,例如: 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(); 第一個alert將會顯示“underfined”,這是因為myname被認為是在函數(shù)內(nèi)部的局部變量(盡管是在之后聲明的)。所以變量的定義都會被吊裝到函數(shù)頂部。因此,要避免這種混亂,最好的方式就是在前期聲明所有打算使用到的變量。 13,創(chuàng)建高效的for循環(huán):使用for循環(huán)來遍歷javascript集合,應(yīng)將集合的長度緩存到一個變量,并使用改變量作為for循環(huán)的條件,例如: 01. for ( var i = 0; i < myarray.length; i++) { //antipattern use of collection length 02. // do something with myarray 03. } 04. 05. //Right pattern 06. var arrLength = myarray.length; 07. for ( var i = 0; i < arrLength; i++) { 08. // do something with myarray 09. } 14,使用hasOwnProperty:在遍歷對象的屬性的時候,使用hasOwnProperty方法來過濾原型鏈屬性是相當重要的,例如: 1. var man = {hands: 2, legs: 2, head: 1}; 2. //somewhere else in the code 3. // a method was added to all object 4. If( typeof Object.prototype.clone === undefined){ 5. Object.prototype.clone = function (){}; 6. } 在定義了man之前,對象原型添加了一個有用的名為clone的方法。原型鏈的存在意味著所以對象都會自動獲得該新方法。為了避免在枚舉man的時候顯示clone方法,就需要調(diào)用hasOwnProperty方法來過濾原型方法,例如: 01. // 1. 02. // for-in loop 03. for ( var i in man) { 04. if (man.hasOwnProperty(i)) { // filter 05. console.log(i, ":" , man[i]); 06. } 07. } 08. /* 09. 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. */ 15,使用===代替==:javascript在比較隱式類型變量的時候,會進行類型轉(zhuǎn)換,而這也就是為什么在比較“false== 0”或“"" == 0”時返回true的原因。為了避免因隱式類型轉(zhuǎn)換所造成的混亂,在比對值與不同的類型表達式的時候,應(yīng)始終使用===或!==操作符來進行檢查。 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. } 另一學(xué)派的觀點是,當使用==已經(jīng)足矣的時候,使用===就顯得有掉多余,例如,當使用typeof的時候,明確返回的是字符串,這時候就沒必要使用恒等。不過JSLint要求嚴格的相等,它要求代碼保持一致的外觀以及減少閱讀代碼的精力(這個==是故意還是遺漏?)。 16,不要使用eval:一定要記住“eval是魔鬼”這句口頭禪。這個函數(shù)可接受任意的字符串,并將字符串作為javascript代碼執(zhí)行,例如: 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" 因此,在這里使用eval會將un定義為一個數(shù)字直接量。假如把jsstrig的值作為用戶的輸入值,這將會導(dǎo)致不少的安全問題。所以,使用eval會帶來安全隱患。 17,parseInt的正確用法:正確使用parseInt的redix可以避免一些不必要的結(jié)果,例如: 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. 因此,要永遠記住使用第二個變量,即redix,來定義數(shù)字的類型,無論它是十進制、八進制還是十六進制。 18,小心函數(shù)吊裝:該問題類似于上面討論的變量吊裝。他們唯一的區(qū)別是只在使用函數(shù)聲明才會發(fā)生,而不是匿名函數(shù)。函數(shù)聲明這種情況,函數(shù)聲明被吊裝時,不單只是聲明問題,處理不當就會出現(xiàn)一些非預(yù)想的結(jié)果,例如: 01. // antipattern 02. // for illustration only 03. // global functions 04. function foo() { 05. alert( 'global foo' ); 06. } 07. function bar() { 08. alert( 'global bar' ); 09. } 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 : 21. // only variable 'bar' gets hoisted 22. // not the implementation 23. var bar = function () { 24. alert( 'local bar' ); 25. }; 26. } 27. hoistMe(); 在示例中,會看到就像普通變量一樣,無論foo或bar自身位于hoistMe的任何地方,都會將他們移動到頂部,重寫全局的foo和bar。不同的地方是本地(local)的foo定義被吊裝到頂部并能正常工作,盡管它是在后面定義的。而bar的定義則不會被吊裝,只是進行了聲明。這就是為什么直到代碼執(zhí)行到bar的定義,會發(fā)現(xiàn)它是undefined且不能作為函數(shù)使用(同時阻止了全局的bar出現(xiàn)在作用域鏈中)。 19,將屬性添加到全局命名空間:在將一個屬性添加到全局命名空間或全局對象的時候,要小心,或許這已經(jīng)存在了,可能會覆蓋掉他們。因此,在添加一個屬性或創(chuàng)建命名空間之前,最好先檢查一下它是否存在,例如: 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 || {}; 為了避免在全局命名空間創(chuàng)建任何成員時編寫這些樣板代碼,可以創(chuàng)建一些可重用的代碼,將要創(chuàng)建的對象傳遞過去,讓代碼去執(zhí)行上述驗證并決定添加或放棄對象。 20,利用JSLint:JSLint會獲取javascript源代碼并掃描他們。如果發(fā)現(xiàn)問題,它會返回問題描述和大致位置的消息。問題不一定是語法錯誤,盡管經(jīng)常會是。JSLint專注于一些風格約定和結(jié)構(gòu)問題。這并不能說明你的程序是正確,只是提供一些方式來協(xié)助發(fā)現(xiàn)問題。只需要簡單的粘貼腳本,它就可以快速的掃描代碼并找出任何明顯的問題和錯誤。 21,避免使用with語句:乍看上去,With語句看上去不賴,主要原因是它可以提供一種簡單方式來訪問嵌套很深的對象,例如: 1. with (being.person.man.bodyparts) { 2. arms = true ; 3. legs = true ; 4. } 代替: 1. being.person.man.bodyparts.arms = true ; 2. being.person.man.bodyparts.legs= true ; 不幸的是,經(jīng)過一些測試后,會發(fā)現(xiàn)他們在設(shè)置新成員時的表現(xiàn)非常糟糕,替代方法是,可以使用var: 1. var o = being.person.man.bodyparts; 2. o.arms = true ; 3. o.legs = true ; 22,使用Ext JS內(nèi)部函數(shù)來添加或移除Ext JS組件的元素:要將一些對象添加到Ext JS容易,不建議使用以下代碼: 1. componentObj.items.items[0] = newObject; 以上代碼的問題:如果使用以上代碼將一些東西添加到容易,Ext JS的所有內(nèi)部任務(wù)就不會在將對象添加到容器時執(zhí)行,而這將會引起一些問題。 解決:應(yīng)使用容器的add方法,或使用組件其他類似的內(nèi)部函數(shù)來處理。 23,從Ext JS的組件中返回組件:要從Ext JS的組件中返回對象,不要使用以下代碼: 1. var anObj = componentObject.items.items[0].items.items[1]; 問題:如果在上述層次結(jié)構(gòu)加入了一個新的層,如一個面板或容器,那么整個層次結(jié)構(gòu)就會變得不穩(wěn)定,可能會返回錯誤的結(jié)果。 解決:使用Ext.getCmp或queryById來代替過長的層級遍歷。盡管這比層級遍歷要慢,但可保證不會出現(xiàn)以上所說層次問題。 (譯者注:在4中,可使用down或up方法查詢子組件或父組件) 24,編寫可讀、可調(diào)試和可重用的代碼:在編寫代碼時,開發(fā)人員應(yīng)創(chuàng)建短小且有意義的類或函數(shù)。不要試圖去把大量的代碼寫在一個單獨的塊中。盡量保持代碼塊短小,從而讓它跟易于重復(fù)使用,且更易于閱讀。 25,使用get/set方法:如果使用config配置項來定義類的變量,Ext JS會自動創(chuàng)建變量的修改方法(setter)和訪問方法(getter),使用這些修改方法和訪問方法可提供代碼的可讀性。如果使用這些方法來而不是直接使用變量名,還可以重寫這些方法或為這些方法添加功能。因此,應(yīng)盡可能使用訪問方法和修改方法作為類這層的變量并使用他們。 26,永遠不要使用自動布局來創(chuàng)建組件:一些常見的錯誤就是因為Ext JS開發(fā)人員在創(chuàng)建容器的時候忘記為他們定義布局了。盡管這在一些瀏覽器上或特定版本的瀏覽器會運行得很好,但從長遠來看,這會導(dǎo)致某些部件出現(xiàn)黑屏或失真等問題,例如: 01. Ext.create(‘Ext.panel.Panel’,{ 02. height: 200, 03. width: 500, 04. //layout: ‘hbox’, // anti pattern if layout is not defined 05. items:[ 06. { 07. xtype: ‘button’, 08. id: ‘button1’ 09. flex: 1 10. },{ 11. xtype: ‘button’, 12. id: ‘button2’ 13. flex: 1 14. } 15. ] 16. }); 在這里,在面板中沒有定義布局,面板的高度和寬度將不會根據(jù)它的組件的flex值進行分配。原因就是容器的布局不知道如何將容器的高度和寬度分配給容器的組件。如果把“l(fā)ayout:hbox”的注釋去掉,這兩個按鈕將會根據(jù)父容器調(diào)整寬帶和高度。 27,避免使用固定的高度和寬度:千萬不要在應(yīng)用程序中固定任何容器或組件的高度和寬度,因為這會破壞應(yīng)用程序的布局流動性。盡量將最頂層的容器或viewport的高度和寬度定義為屏幕大小,然后小心的通過正確的使用flex或布局將這個尺寸分分派給子組件或子容器,不要使用硬編碼的高度或?qū)挾?,也可以通過使用Ext JS的功能來計算,如Ext.getBody().getViewSize().height或Ext..getBody().width: 1. Ext.create(“Ext.panel.Panel”,{ 2. height: Ext.getBody().getViewSize().height, 3. width: Ext.getBody().getViewSize().width 4. }); 28,正確使用flex關(guān)鍵字:flex是一個用來保持流動性布局的非常重要的關(guān)鍵字,該值通常用來決定如何接收父容器的尺寸,例如,如果兩個組件的定義分別為flex=1和flex=2,那么,這兩個組件從父容器接收到的尺寸比例就是1:2。在這里,還需要留意另一個重點,就是該值只用來劃分父容器的寬度或高度,而不能同時來決定子組件的寬度和高度,例如: 01. Ext.create(‘Ext.panel.Panel’,{ 02. height: 200, 03. width: 500, 04. layout: ‘hbox’, 05. items:[ 06. { 07. xtype: ‘button’, 08. id: ‘button1’ 09. flex: 1 10. },{ 11. xtype: ‘button’, 12. id: ‘button2’ 13. flex: 1 14. } 15. ] 16. }); 以上代碼,使用了水平盒子布局,因而,只有按鈕的寬度會根據(jù)flex值的比例進行劃分,而兩個按鈕的高度則會是100%,即是每個按鈕的寬度會是250,而高度是200。同樣,如果將面板的布局修改為垂直盒子布局,那么,每一個按鈕的寬度將會是500,而高度會是100。因此,要適當并謹慎地使用flex來實現(xiàn)更好的流動布局。 29,盡量少用minxWidth、maxWidth、minHeight和maxHeight:盡量在需要的時候才使用這些屬性,否則就不要使用他們,因為在組件布局方面,他們的使用是非常昂貴的。如果在組件中碰到這些屬性,布局會重新進行計算,因此,這樣的代價非常昂貴。 30,使用Sencha Cmd工具來壓縮(minification)代碼:進行壓縮處理時,會消除空白、注釋和javascript代碼中其他不重要的部分,這樣可減少javascript文件的大小,從而減小服務(wù)器到瀏覽器的傳輸量。另外,壓縮處理還會重命名變量為較短的名稱(但只有在它是安全的時候),如前面代碼中的參數(shù)D、C、B或A。壓縮處理只會重命名局部變量,因為重命名全局變量可能破壞代碼。這也是為什么使用局部變量是一個好做法的主要愿意。如果在一個函數(shù)內(nèi),使用全局變量,如DOM引用,超過一到兩次,那就給它分配一個局部變量,這是好的做法。這些通常需要一些工具(壓縮)來實現(xiàn),如Ext JS命令行工具(只適用于Ext JS的應(yīng)用程序開發(fā))、雅虎的YUICompressor或谷歌的Closure Complier(適用于普通的javascript應(yīng)用程序),這喲這樣加快頁面加載時間。壓縮為生產(chǎn)準備的腳本是十分重要的,因為最終可以將文件的大小大大壓縮,通??梢詨嚎s一半的大小。 31,保持DOM的輕量化:盡量保持DOM的輕量化可加快DOM的訪問和維護速度。這可通過移除不必要的DOM元素來實現(xiàn),例如,如果使用卡片布局,且每個卡片都要顯示大量容器或組件,而且用戶不會返回之前的卡片,最好的方式就是在程序(這樣所需的容器或組件就不會再次創(chuàng)建)中緩存DOM元素,然后將DOM 32,盡量減少DOM訪問:DOM訪問是昂貴的,它是javascript性能最常見的瓶頸。這是因為DOM的實現(xiàn)通常是與javascript引擎分離的。底線就是應(yīng)將DOM訪問減少到最低限度,這意味著:
33,不要創(chuàng)建內(nèi)聯(lián)處理函數(shù):千萬必要創(chuàng)建內(nèi)聯(lián)函數(shù),因為對于回調(diào)會監(jiān)聽所使用的函數(shù)來說,是常見的問題源。他們不單需要花費時間來創(chuàng)建,還需要昂貴的閉包,例如: 1. Ext.define(‘MyClass’,{ 2. constructor: function (config){ 3. this .store.on(‘load’, function (){ 4. ………..; 5. }, this ); 6. } 7. }); 以上代碼,每當構(gòu)造函數(shù)執(zhí)行一次,就會創(chuàng)建一個新的監(jiān)聽函數(shù),這不單需要花費時間處理閉包問題,還潛在內(nèi)存泄漏問題。以下是首選的模式: 1. Ext.define(‘MyClass’,{ 2. constructor: function (config){ 3. this .store.on(‘load’, this .onStoreLoad, this ); 4. }, 5. onStoreLoad: function (){ 6. ………; 7. } 8. }); 在以上代碼中,監(jiān)聽函數(shù)只會創(chuàng)建一次并保存在類中。每個實例都會共享相同的函數(shù)。創(chuàng)建函數(shù)的開銷只有一次,而且沒有閉包泄漏的風險。更重要的是,這樣的編碼風格,還可以讓子類輕松的去重寫監(jiān)聽。 34,正確使用xtype:一個常見的神話就是xtype可通過延遲初始化提高性能。通常,這不是真的。盡管通過xtype配置項將組件添加到容器,它還是進行實例化,盡管它還不可見。雖然xtype有很大用途,但對于應(yīng)用程序的性能或資源消耗來說沒有實際可衡量的影響。 35,千萬不要使用整個ext-all.js庫:通常,ext-all.js是包含了全部功能和組件的巨大編碼集,但我們很少會使用到Ext JS的全部功能和組件,因此,沒必要在只使用了60%到70%代碼的時候去加載一個巨大的文件??梢允褂肧encha命令行工具來壓縮生產(chǎn)代碼,它會從ext-all.js中復(fù)制所需的類并粘貼到結(jié)果all-classes.js。如果沒有使用Sencha命令行工具,還可以通過其他方式來確保不用加載整4個ext-all.js文件。 36,批處理任務(wù):盡量使用批處理進行更新,以便渲染只在最后時刻觸發(fā)一次渲染。例如,修改記錄的字段值會立即更新到網(wǎng)格,如果想讓幾個字段的更新更高效,就進行批處理,例如: 1. record.beginEdit(); 2. record.set(‘name’, ‘Tom’); 3. record.set(‘a(chǎn)ge’, 17); 4. record.set(‘member’, true ); 5. record.endEdit(); 如果要修改的字段更多,效果會更明顯。 01. //slow code 02. container.add(panel); 03. container.add(button); 04. container.add(grid); 05. 06. //fast 07. container.add(panel, button, grid); 08. 09. //using an array is also fast 10. container.add([panel, button, grid]); 在沒有其他批處理機制的時候,可以使用暫停布局來臨時輔助實現(xiàn): 1. container.suspendLayout = true ; 2. doSomethingToChangeLotsOfLayoutChange(); 3. container.suspendLayout = false ; 4. container.doLayout(); 37,使用deferredRender:在使用卡片布局或標簽面板的時候,要認真考慮一下deferredRender選項。當將它設(shè)置為true,就可以將隱藏的條目或選項卡實現(xiàn)延遲渲染。只有在隱藏的條目第一次顯示的時候,才會進行渲染。當設(shè)置為false,所以的卡片或標簽就會作為容器渲染的一部分在同一時間進行渲染。 38,網(wǎng)格的緩沖渲染:在使用網(wǎng)格的時候,如果數(shù)據(jù)集很打,使用緩沖渲染吧。這意味著在加載存儲的時候,存儲要維持一個“預(yù)讀”緩沖,以保存將要使用到的記錄頁。 01. myStore = ……{ 02. …………., 03. Buffered: true , // Tell grid to use a paging scroll manager to scroll and refresh table automatically. 04. perPageCount: 0 // never remove pages from the prefetch buffer; 05. } 06. 07. myStore.prefetch({ 08. start: 0, 09. limit: 999999, 10. callback: function (){ 11. myStore.load(0, 49); 12. } 13. }); 預(yù)讀所有所預(yù)期的數(shù)據(jù)集后,回調(diào)會加載存儲的主緩存(映射到網(wǎng)格面板內(nèi)的緩存)所使用的50行數(shù)據(jù)。由于只能得到小于50行的表格,所以在滾動接近視圖邊界的時候,它就會更新。該技術(shù)在4.0.x工作OK,不過在4.1.0進行了翻修,變得更快和更平滑。在網(wǎng)格目錄的緩沖網(wǎng)格示例延時該技術(shù)。 39,在標簽面板的每個標簽頁的beforeRender事件處理中填充標簽頁:在beforeRendere中填充標簽頁是更好的方法。正確的實現(xiàn)這個可以有效的改進包含大量未渲染組件的應(yīng)用程序的性能。雖然實例化一個組件的時間比渲染或布局所需要的時間要小,但如果有大量的未渲染組件也需要時間。帶有許多標簽頁的標簽面板這樣處理會更理想。要特別支出的是,我建議的只是shuffle time around:cut the time taken for the initial load in favour of slightly slower tab transitions.這只是你武器庫中的另一種技術(shù)。與以往一樣,優(yōu)化的黃金規(guī)則是在實現(xiàn)之前,要做一些有意義的測量。 40,使用mon代替on:這兩個關(guān)鍵字都是用來事件處理綁定到事件的。不過,使用mon而不是on會更高效,因為這可確保監(jiān)聽會在MyClass的實例被銷毀的時候自動移除它,例如: 01. Ext.define(‘MyClass’,{ 02. Constructor: function (config){ 03. //this.store.on(‘load’, this.onStoreLoad, this); // this is not good 04. this .store.mon(‘load’, this .onStoreLoad, this ); 05. }, 06. onStoreLoad: function (){ 07. ………; 08. } 09. 10. }); 41,在事件處理程序中不要保留對this的引用:通常,在任何Ext JS組件的內(nèi)聯(lián)事件處理函數(shù)工作時,都需要使用this關(guān)鍵字來獲取相應(yīng)類的對象的應(yīng)用。通常情況下,組件的事件處理程序的this指向的是該組件這個對象。隱藏,要解決這個問題,一些開發(fā)人員會在構(gòu)造函數(shù)或類的initComponent方法內(nèi)使用一些全局變量來引用類,然后在內(nèi)聯(lián)處理中使用全局變量來獲取相應(yīng)的類對象,不過,這是錯誤的做法,我們贏遵循這里的約定。 42,嘗試使用客戶端緩存:本地存儲、session存儲、sqllite等等。如果使用HTML5,就可以將一些數(shù)據(jù)保持在客戶端(不是cookie),并在再次瀏覽該頁時使用這些數(shù)據(jù)。這樣,就可以避免將一些沒必要的東西發(fā)送到服務(wù)器或數(shù)據(jù)庫。在Ext JS,可以使用代理來處理這類緩存。在Ext JS中有兩類代理:ClientProxy和ServerProxy。ClientProxy就是用來處理客戶端緩存的。有以下三種類型的ClientProxy:
除了這些,一些瀏覽器,如chrome,還支持一些特殊類型的客戶端數(shù)據(jù),如SQLLite,它可以在客戶端存儲一些數(shù)據(jù)。因此,通過使用這些技術(shù),可以用來提高應(yīng)用程序的性能。 43,不要使用Array.isArray:Array.isArray(anyObject)方法用來判斷anyObject是否一個數(shù)組對象。該方法只能在Chrome中工作,不能在IE中工作。IE并不能識別該方法并會給出錯誤??墒褂胕nstanceof來替代該方法來達到相同的目的。instanceof方法既可在IE工作,也可在Chrome工作。 44,一定要注意日期格式:在解析日期的時候,要注意日期字符串的格式是否既支持IE,又支chrom: 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" ; 不要使用var dateString = "Oct/02/2011",IE不支持,在chrome中是支持的。我已經(jīng)在應(yīng)用程序修正了這個。 45,別忘了以下要點:以下是在將代碼發(fā)布為產(chǎn)品時不應(yīng)忘記的一些要點:
作者: Raja 譯者: 黃燈橋 |
|