【翻译】Ext JS——高效的编码风格指南

原文:ExtJS - Efficient coding style guide

作者:Raja

  1. 切勿使用“new”keyword:在Ext JS中,使用“new”keyword来创建一个组件或类的实例是一种错误的做法,由于这没有遵循组件的生命周期。应该使用Ext.create方法来创建对象。比如:
    错误: var obj = new Ext.panel.Panel();
    
    正确: var obj = Ext.create(‘Ext.panel.Panel’);
    
    
  2. 初始化直接量:不要直接创建直接量的对象,比如。使用下面javascript来创建空白对象:
     var stringObj = new String();
    var arrayObj = new Array();
    var obj = new Object();
    

    在javascript中,以上都是创建对象的不对方式,这是由于假设使用这些处理方式,控制须要去遍历整个类的层次。因此,作为替代。能够使用下面方式来创建这些类的对象:
     var stringObj = ‘’;
    var arrayObj = [];
    var obj = {};
    

    只是,你接手的可能是别人编写的遗留代码。因而会注意到构造函数的一个“特色”(这或者是还有一个不使用它的理由)。“特色”的主要问题是Object的构造函数可接受參数,并且它会依据传入的值来决定是否将对象的创建托付给还有一个内置构造函数,而终于返回的对象可能不是你所预期的。比如:
     // Warning: antipatterns ahead
    // an empty object
    var o = new Object();
    console.log(o.constructor === Object); // true
    // a number object
    var o = new Object(1);
    console.log(o.constructor === Number); // true

  3. 更聪明的使用getCmp:它将依据传递的id值返回匹配的对象(Ext JS对象)。这是一种高速返回对象的方法。

    全部对象在创建的时候,都须要使用他们的id作为keyword注冊为一个单一对象,这样,使用Ext.getCmp(myId)就能够寻找并返回RegistrationObject["myId"]。因此,这会变得很快捷。



    只是,假设都个组件使用了同样的id。它就会失效。在这样的情况下。它将会返回最后一个查找到的对象。基于这点,建议尽量不要使用这个来获取对象。

    建议的做法是仅仅使用该方法一次,然后将结果保存到一个变量,再在其它地方通过变量来引用对象。

    假设须要为多个组件定义同样的id,建议使用itemId。通过这篇文章可了解id和itemId直接的不同。



  4. 避免不比亚的全局变量:使用全局变量的主要问题就是它可在javascript应用程序或Web页面中共享全部代码。这可能会与使用同样名称的命名空间引起冲突,在应用程序的两个单独部分定义具有同样名称但用途不同的全局变量的可能性是存在的。

    使用不必要的全局变量的第二个缺点是会造成更大的内存损耗,这是由于,对于这些全局变量。普通情况下是不会进行垃圾回收的,因而不会释放内存。

  5. 使用varkeyword来定义全局变量:使用var来定义全局变量与不使用之间的一个细微差别是:能不能使用delete操作符来删除这些变量。
    使用var来定义的全局变量(包括在函数内创建的)不能使用delete来删除。比如:
                     // define three globals
    var global_var = 1;
    global_novar = 2; // antipattern
    (function () {
                    global_fromfunc = 3; // antipattern
    }());
    // attempt to delete
    delete global_var; // false
    delete global_novar; // true
    delete global_fromfunc; // true
    // test the deletion
    typeof global_var; // "number"
    typeof global_novar; // "undefined"
    typeof global_fromfunc; // "undefined"

  6. 尝试去删除那些未使用的变量和函数:不要保留代码中那些没有使用到的变量、函数或者不必要的凝视,由于这些仅仅会添加文件的大小。从而添加文件的载入时间。

  7. 避免在循环中创建对象或变量:假设没有必要。就不要在循环中创建单一的变量或对象。由于他们的数量会随着选好的迭代次数而添加,进而造成内存泄漏。

  8. 避免过度使用面板:在大多数情况下,Ext JS应用程序会受到面板过度使用的影响。不管什么情况都使用面板。或者更准确的说,是不管不论什么情况下都会使用多个面板。解决的方法就是在使用一些轻量级的替代品来取代面板。很多人都喜欢面板,只是说实在,在UI的很多部分有点过分了。我以前看到一个用来显示几十个缩略图的UI,每一个图像都是使用不同面板的HTML内容来显示的,而这些面板是全然不是必需的。能够考虑下面替代方法……
    • 是否可使用HTML和CSS,而不是完整的组件?使用Ext.Template或Ext.XTemplate可能更实际。

    • 能否够使用自己定义的Ext.Component?能够使用不同的配置项来将HTML猪肉到组件:autoEl、html、tpl或数据。
    • 能否够使用数据视图(DataView)来渲染全部数据而不是单独的组件?
    • 能否够使用Ext.container.Container,而不是Ext.panel.Panel来降低开销?

  9. 避免容器嵌套:尽量避免不必要地使用容器。由于每一个容器都会创建一个层次结构,并以此为核心来訪问子组件,而这,须要遍历这些容器的层次结构。因此。要尽量在最小的可能容器数量下创建视图。

  10. 函数要尽可能小:每一个函数都应短小精干和有意义。

    大的函数会降低可读性、可维护性、可重用性和可调试性。除此之外,假设一个对象(很消耗内存的对象)在函数開始时进行实例化,它就会一直存在到函数结束。

    所以。假设函数很小。那么,它的局部变量、对象等垃圾就能够在更短的时间跨度内被回收,从而释放内存于其它用途。

  11. 尽量避免过长的对象引用:应尽量避免大型对象的引用,由于这须要花费很多其它的时间来遍历对象的层次结构来获取所需的组件,比如:
         var arrayLength = arrayObj.lenght;
        for( var I = 0; I < arrayLenght; i++){
                    //anti pattern
                    If(Abc.xyz.foo.bar.againFoo.againBar.finalObj === arrayObj[i]){
                                    Alert(‘Anti pattern code’);
                    }
       }

    以上代码可重写为下面更有效的方式:
         var arrayLength = arrayObj.lenght;
        var obj = Abc.xyz.foo.bar.againFoo.againBar.finalObj;
        for( var I = 0; I < arrayLenght; i++){
                    //pattern
                    If(obj === arrayObj[i]){
                                    Alert(‘pattern code’);
                    }
        }
    

  12. 应避免吊装(hoisting)问题:javascript同意在一个函数内不论什么个地方使用多个var语句,而他们的行为与在函数顶部定义变量是没有差别的。这样的行为通常被称为吊装。在使用变量之后再在函数内进行声明,可能会导致逻辑错误。对于javascript来说,仅仅要变量在同一作用域(同一函数)被使用,它就会被声明,不管是否使用了var来定义。比如:
            // antipattern
            myname = "global"; // global variable
            function func() {
                   alert(myname); // "undefined"
                   var myname = "local";
                   alert(myname); // "local"
            }
            func();

    第一个alert将会显示“underfined”。这是由于myname被觉得是在函数内部的局部变量(虽然是在之后声明的)。所以变量的定义都会被吊装到函数顶部。

    因此,要避免这样的混乱,最好的方式就是在前期声明全部打算使用到的变量。



  13. 创建高效的for循环:使用for循环来遍历javascript集合,应将集合的长度缓存到一个变量。并使用改变量作为for循环的条件,比如:

            for (var i = 0; i < myarray.length; i++) { //antipattern use of collection length
                // do something with myarray
           }
    
          //Right pattern
          var arrLength =  myarray.length;
          for (var i = 0; i < arrLength; i++) {
               // do something with myarray
          }

  14. 使用hasOwnProperty:在遍历对象的属性的时候,使用hasOwnProperty方法来过滤原型链属性是相当重要的。比如:
              var man = {hands: 2, legs: 2, head: 1};
             //somewhere else in the code
            // a method was added to all object
            If( typeof Object.prototype.clone === undefined){
                    Object.prototype.clone = function(){};
            }
    

    在定义了man之前。对象原型加入了一个实用的名为clone的方法。原型链的存在意味着所以对象都会自己主动获得该新方法。

    为了避免在枚举man的时候显示clone方法,就须要调用hasOwnProperty方法来过滤原型方法,比如:

       // 1.
          // for-in loop
          for (var i in man) {
                 if (man.hasOwnProperty(i)) { // filter
                        console.log(i, ":", man[i]);
                 }
           }
           /*
              result in the console
              hands : 2, legs : 2, heads : 1
           */
           // 2.
          // antipattern:
         // for-in loop without checking hasOwnProperty()
          for (var i in man) {
               console.log(i, ":", man[i]);
          }
         /*
          result in the console
          hands : 2, legs : 2, heads : 1, clone: function()
        */



  15. 使用===取代==:javascript在比較隐式类型变量的时候,会进行类型转换。而这也就是为什么在比較“false== 0”或“"" == 0”时返回true的原因。为了避免因隐式类型转换所造成的混乱,在比对值与不同的类型表达式的时候,应始终使用===或!==操作符来进行检查。
              var zero = 0;
             if (zero === false) {
                   // not executing because zero is 0, not false
             }
             // antipattern
             if (zero == false) {
                   // this block is executed...
             }

    还有一学派的观点是。当使用==已经足矣的时候。使用===就显得有掉多余,比如,当使用typeof的时候。明白返回的是字符串,这时候就不是必需使用恒等。

    只是JSLint要求严格的相等,它要求代码保持一致的外观以及降低阅读代码的精力(这个==是有益还是遗漏?)。

  16. 不要使用eval:一定要记住“eval是魔鬼”这句口头禅。这个函数可接受随意的字符串,并将字符串作为javascript代码运行,比如:
              console.log(typeof un); // "undefined"
             var jsstring = "var un = 1; console.log(un);";
             eval(jsstring); // logs "1"
             console.log(typeof un); // "number"

    因此,在这里使用eval会将un定义为一个数字直接量。

    假如把jsstrig的值作为用户的输入值,这将会导致不少的安全问题。所以,使用eval会带来安全隐患。

  17. parseInt的正确使用方法:正确使用parseInt的redix能够避免一些不必要的结果,比如:
     alert(parseInt("8")); // "Will print 8"
    alert(parseInt("08")); // "Will print 0"
    alert(parseInt("08,10")); // "Will print 8"
    If we use parseInt(“08”), it gives octal value of 08.
    
    因此,要永远记住使用第二个变量,即redix。来定义数字的类型,不管它是十进制、八进制还是十六进制。

  18. 小心函数吊装:该问题相似于上面讨论的变量吊装。他们唯一的差别是仅仅在使用函数声明才会发生,而不是匿名函数。函数声明这样的情况。函数声明被吊装时,不单仅仅是声明问题,处理不当就会出现一些非预想的结果,比如:
     // antipattern
    // for illustration only
    // global functions
    function foo() {
    alert('global foo');
    }
    function bar() {
    alert('global bar');
    }
    function hoistMe() {
    console.log(typeof foo); // "function"
    console.log(typeof bar); // "undefined"
    foo(); // "local foo"
    bar(); // TypeError: bar is not a function
    // function declaration:
    // variable 'foo' and its implementation both get hoisted
    function foo() {
    alert('local foo');
    }
    // function expression:
    // only variable 'bar' gets hoisted
    // not the implementation
    var bar = function () {
    alert('local bar');
    };
    }
    hoistMe();

    在演示样例中,会看到就像普通变量一样。不管foo或bar自身位于hoistMe的不论什么地方,都会将他们移动到顶部,重写全局的foo和bar。不同的地方是本地(local)的foo定义被吊装到顶部并能正常工作。虽然它是在后面定义的。而bar的定义则不会被吊装,仅仅是进行了声明。

    这就是为什么直到代码运行到bar的定义。会发现它是undefined且不能作为函数使用(同一时候阻止了全局的bar出如今作用域链中)。

  19. 将属性加入到全局命名空间:在将一个属性加入到全局命名空间或全局对象的时候。要小心。也许这已经存在了,可能会覆盖掉他们。因此。在加入一个属性或创建命名空间之前,最好先检查一下它是否存在,比如:
     // unsafe and antipattern
    var MYAPP = {};
    // better
    if (typeof MYAPP === "undefined") {
    var MYAPP = {};
    }
    // or shorter
    var MYAPP = MYAPP || {};
    

    为了避免在全局命名空间创建不论什么成员时编写这些样板代码。能够创建一些可重用的代码。将要创建的对象传递过去,让代码去运行上述验证并决定加入或放弃对象。

  20. 利用JSLint:JSLint会获取javascript源码并扫描他们。假设发现问题,它会返回问题描写叙述和大致位置的消息。问题不一定是语法错误,虽然经常会是。JSLint专注于一些风格约定和结构问题。这并不能说明你的程序是正确。仅仅是提供一些方式来协助发现问题。仅仅须要简单的粘贴脚本,它就能够高速的扫描代码并找出不论什么明显的问题和错误。
    网址:http://www.jslint.com/

  21. 避免使用with语句:乍看上去,With语句看上去不赖,主要原因是它能够提供一种简单方式来訪问嵌套很深的对象。比如:
     with (being.person.man.bodyparts) {  
                                    arms = true;  
                                    legs = true;  
                     }

    取代:
     being.person.man.bodyparts.arms = true;  
                    being.person.man.bodyparts.legs= true;
    

    不幸的是,经过一些測试后,会发现他们在设置新成员时的表现很糟糕,替代方法是,能够使用var:
                                      var o = being.person.man.bodyparts;  
                                    o.arms = true;  
                    o.legs = true;
    


  22. 使用Ext JS内部函数来加入或移除Ext JS组件的元素:要将一些对象加入到Ext JSeasy,不建议使用下面代码:
    componentObj.items.items[0] = newObject;

    以上代码的问题:假设使用以上代码将一些东西加入到easy,Ext JS的全部内部任务就不会在将对象加入到容器时运行,而这将会引起一些问题。

    解决:应使用容器的add方法,或使用组件其它相似的内部函数来处理。

  23. 从Ext JS的组件中返回组件:要从Ext JS的组件中返回对象。不要使用下面代码:
     var anObj = componentObject.items.items[0].items.items[1];
    

    问题:假设在上述层次结构加入了一个新的层,如一个面板或容器。那么整个层次结构就会变得不稳定,可能会返回错误的结果。



    解决:使用Ext.getCmp或queryById来取代过长的层级遍历。虽然这比层级遍历要慢,但可保证不会出现以上所说层次问题。

    (译者注:在4中。可使用down或up方法查询子组件或父组件)

  24. 编写可读、可调试和可重用的代码:在编写代码时,开发者应创建短小且有意义的类或函数。

    不要试图去把大量的代码写在一个单独的块中。尽量保持代码块短小。从而让它跟易于反复使用,且更易于阅读。

  25. 使用get/set方法:假设使用config配置项来定义类的变量,Ext JS会自己主动创建变量的改动方法(setter)和訪问方法(getter)。使用这些改动方法和訪问方法可提供代码的可读性。

    假设使用这些方法来而不是直接使用变量名,还能够重写这些方法或为这些方法加入功能。因此,应尽可能使用訪问方法和改动方法作为类这层的变量并使用他们。

  26. 永远不要使用自己主动布局来创建组件:一些常见的错误就是由于Ext JS开发者在创建容器的时候忘记为他们定义布局了。虽然这在一些浏览器上或特定版本号的浏览器会运行得很好,但从长远来看,这会导致某些部件出现黑屏或失真等问题,比如:
     Ext.create(‘Ext.panel.Panel’,{
                    height: 200,
                     500,
                    //layout: ‘hbox’,          // anti pattern if layout is not defined
                    items:[
                                    {
                                                    xtype: ‘button’,
                                                    id: ‘button1’
                                                    flex: 1
    },{
                                                    xtype: ‘button’,
                                                    id: ‘button2’
                                                    flex: 1
    }
    ]
    });
    

    在这里,在面板中未定义布局,面板的高度和宽度将不会依据它的组件的flex值进行分配。原因就是容器的布局不知道怎样将容器的高度和宽度分配给容器的组件。假设把“layout:hbox”的凝视去掉,这两个按钮将会依据父容器调整宽带和高度。

  27. 避免使用固定的高度和宽度:千万不要在应用程序中固定不论什么容器或组件的高度和宽度,由于这会破坏应用程序的布局流动性。尽量将最顶层的容器或viewport的高度和宽度定义为屏幕大小。然后小心的通过正确的使用flex或布局将这个尺寸分分派给子组件或子容器,不要使用硬编码的高度或宽度,也能够通过使用Ext JS的功能来计算,如Ext.getBody().getViewSize().height或Ext..getBody().width:
     Ext.create(“Ext.panel.Panel”,{
                    height: Ext.getBody().getViewSize().height,
                     Ext.getBody().getViewSize().width
    });
    

  28. 正确使用flexkeyword:flex是一个用来保持流动性布局的很重要的keyword。该值通经常使用来决定怎样接收父容器的尺寸,比如。假设两个组件的定义分别为flex=1和flex=2,那么,这两个组件从父容器接收到的尺寸比例就是1:2。在这里,还须要留意还有一个重点,就是该值仅仅用来划分父容器的宽度或高度,而不能同一时候来决定子组件的宽度和高度。比如:
     Ext.create(‘Ext.panel.Panel’,{
                    height: 200,
                     500,
                    layout: ‘hbox’,         
                    items:[
                                    {
                                                    xtype: ‘button’,
                                                    id: ‘button1’
                                                    flex: 1
    },{
                                                    xtype: ‘button’,
                                                    id: ‘button2’
                                                    flex: 1
    }
    ]
    });

    以上代码,使用了水平盒子布局,因而,仅仅有按钮的宽度会依据flex值的比例进行划分,而两个按钮的高度则会是100%,即是每一个按钮的宽度会是250。而高度是200。同样,假设将面板的布局改动为垂直盒子布局。那么,每一个按钮的宽度将会是500,而高度会是100。因此,要适当并慎重地使用flex来实现更好的流动布局。



  29. 尽量少用minxWidth、maxWidth、minHeight和maxHeight:尽量在须要的时候才使用这些属性,否则就不要使用他们,由于在组件布局方面,他们的使用是很昂贵的。

    假设在组件中碰到这些属性,布局会又一次进行计算,因此。这样的代价很昂贵。

  30. 使用Sencha Cmd工具来压缩(minification)代码:进行压缩处理时,会消除空白、凝视和javascript代码中其它不重要的部分。这样可降低javascript文件的大小,从而减小server到浏览器的传输量。另外,压缩处理还会重命名变量为较短的名称(但仅仅有在它是安全的时候)。如前面代码中的參数D、C、B或A。

    压缩处理仅仅会重命名局部变量,由于重命名全局变量可能破坏代码。

    这也是为什么使用局部变量是一个好做法的主要愿意。假设在一个函数内,使用全局变量,如DOM引用。超过一到两次。那就给它分配一个局部变量。这是好的做法。

    这些通常须要一些工具(压缩)来实现。如Ext JS命令行工具(仅仅适用于Ext JS的应用程序开发)、雅虎的YUICompressor或谷歌的Closure Complier(适用于普通的javascript应用程序),这哟这样加快页面载入时间。压缩为生产准备的脚本是十分重要的,由于终于能够将文件的大小大大压缩,通常能够压缩一半的大小。

  31. 保持DOM的轻量化:尽量保持DOM的轻量化可加快DOM的訪问和维护速度。这可通过移除不必要的DOM元素来实现。比如,假设使用卡片布局。且每一个卡片都要显示大量容器或组件,并且用户不会返回之前的卡片,最好的方式就是在程序(这样所需的容器或组件就不会再次创建)中缓存DOM元素。然后将DOM
    元素从DOM中移除以让它轻量化。



  32. 尽量降低DOM訪问:DOM訪问是昂贵的,它是javascript性能最常见的瓶颈。

    这是由于DOM的实现一般是与javascript引擎分离的。底线就是应将DOM訪问降低到最低限度,这意味着:

    • 避免在循环中进行DOM訪问
    • 将DOM引用指派给局部变量并使用举报变量进行操作
    • 在可能的情况下。使用API的选择器
    • 当要遍历HTML集合时,缓存集合的长度
    • 尽量使用Ext JS的方法来訪问或维护DOM,以获得跨浏览器支持,否则某些代码在某些浏览器可能会失败,这是由于每一个浏览器都有它自己的DOM訪问方式。
  33. 不要创建内联处理函数:千万必要创建内联函数。由于对于回调会监听所使用的函数来说,是常见的问题源。他们不单须要花费时间来创建,还须要昂贵的闭包,比如:
     Ext.define(‘MyClass’,{
                    constructor: function(config){
                                    this.store.on(‘load’, function(){
                    ………..;
    }, this);
                    }
    });

    以上代码,每当构造函数运行一次。就会创建一个新的监听函数,这不单须要花费时间处理闭包问题,还潜在内存泄漏问题。

    下面是首选的模式:

     Ext.define(‘MyClass’,{
                    constructor: function(config){
                                    this.store.on(‘load’, this.onStoreLoad, this);
                    },
                    onStoreLoad: function(){
                                    ………;
    }
    });

    在以上代码中,监听函数仅仅会创建一次并保存在类中。每一个实例都会共享同样的函数。创建函数的开销仅仅有一次,并且没有闭包泄漏的风险。更重要的是,这样的编码风格,还能够让子类轻松的去重写监听。

  34. 正确使用xtype:一个常见的神话就是xtype可通过延迟初始化提高性能。

    通常。这不是真的。虽然通过xtype配置项将组件加入到容器,它还是进行实例化。虽然它还不可见。虽然xtype有很大用途。但对于应用程序的性能或资源消耗来说没有实际可衡量的影响。



  35. 千万不要使用整个ext-all.js库:通常。ext-all.js是包括了全部功能和组件的巨大编码集,但我们很少会使用到Ext JS的全部功能和组件。因此,不是必需在仅仅使用了60%到70%代码的时候去载入一个巨大的文件。能够使用Sencha命令行工具来压缩生产代码,它会从ext-all.js中复制所需的类并粘贴到结果all-classes.js。假设没有使用Sencha命令行工具。还能够通过其它方式来确保不用载入整4个ext-all.js文件。

  36. 批处理任务:尽量使用批处理进行更新,以便渲染仅仅在最后时刻触发一次渲染。比如。改动记录的字段值会马上更新到网格,假设想让几个字段的更新更高效。就进行批处理,比如:
     record.beginEdit();
    record.set(‘name’, ‘Tom’);
    record.set(‘age’, 17);
    record.set(‘member’, true);
    record.endEdit();

    假设要改动的字段很多其它,效果会更明显。


    还有一个样例是将组件加入到容器。每加入一次,容器就会又一次计算布局一次。将多个组件传递给同一个add方法,将会高效得多,比如:

     //slow code
    container.add(panel);
    container.add(button);
    container.add(grid);
    
    //fast
    container.add(panel, button, grid);
    
    //using an array is also fast
    container.add([panel, button, grid]);

    在没有其它批处理机制的时候,能够使用暂停布局来暂时辅助实现:
     container.suspendLayout = true;
    doSomethingToChangeLotsOfLayoutChange();
    container.suspendLayout = false;
    container.doLayout();



  37. 使用deferredRender:在使用卡片布局或标签面板的时候。要认真考虑一下deferredRender选项。当将它设置为true,就能够将隐藏的条目或选项卡实现延迟渲染。仅仅有在隐藏的条目第一次显示的时候。才会进行渲染。当设置为false,所以的卡片或标签就会作为容器渲染的一部分在同一时间进行渲染。
    延迟渲染通常来说挺好的,这有助于将渲染过程分解为较小的数据块,不会对用户造成明显的延迟。只是。渲染全部的卡片或标签页,在隐藏的卡片或标签页第一次显示的时候有助于改善UI的响应。

  38. 网格的缓冲渲染:在使用网格的时候,假设数据集很打。使用缓冲渲染吧。这意味着在载入存储的时候,存储要维持一个“预读”缓冲,以保存将要使用到的记录页。


    假设数据少于100000行(也取决于每行的列数),最好的方式是在client将全部数据保存到预读缓冲区。


    渲染大的HTML表格会谋杀性能。这其实仅仅是HTML表格算法。仅仅保持所以数据应该不会导致问题。
    要做的仅仅是滚动的时候。在“适当时候”渲染表格的行。要做到这一点,仅仅须要一次载入预读缓冲中的全部数据。这样做后,就能够从预读缓存中载入存储的主要数据,比如:

     myStore = ……{
    ………….,
    Buffered: true, // Tell grid to use a paging scroll manager to scroll and refresh table automatically.
                                    perPageCount: 0 // never remove pages from the prefetch buffer;
    }
    
    myStore.prefetch({
                                    start: 0,
                                    limit: 999999,
                                    callback: function(){
                                    myStore.load(0, 49);
    }
    });

    预读全部所预期的数据集后,回调会载入存储的主缓存(映射到网格面板内的缓存)所使用的50行数据。由于仅仅能得到小于50行的表格,所以在滚动接近视图边界的时候。它就会更新。该技术在4.0.x工作OK。只是在4.1.0进行了翻修,变得更快和更平滑。

    在网格文件夹的缓冲网格演示样例延时该技术。
    要注意的是,太多的列会对HTML的性能产生影响。


    元素太多也会这样。因而须要避免显示不须要的列。



  39. 在标签面板的每一个标签页的beforeRender事件处理中填充标签页:在beforeRendere中填充标签页是更好的方法。正确的实现这个能够有效的改进包括大量未渲染组件的应用程序的性能。虽然实例化一个组件的时间比渲染或布局所须要的时间要小,但假设有大量的未渲染组件也须要时间。带有很多标签页的标签面板这样处理会更理想。要特别支出的是。我建议的仅仅是shuffle time around:cut the time taken for the initial load in favour of slightly slower tab transitions.这仅仅是你武器库中的还有一种技术。与以往一样,优化的黄金规则是在实现之前。要做一些有意义的測量。



  40. 使用mon取代on:这两个keyword都是用来事件处理绑定到事件的。只是。使用mon而不是on会更高效。由于这可确保监听会在MyClass的实例被销毁的时候自己主动移除它,比如:
     Ext.define(‘MyClass’,{
                                    Constructor: function(config){
                                                    //this.store.on(‘load’, this.onStoreLoad, this); // this is not good
                                                    this.store.mon(‘load’, this.onStoreLoad, this);
                                    },
                                    onStoreLoad: function(){
                                                    ………;
    }
    
    });

  41. 在事件处理程序中不要保留对this的引用:通常,在不论什么Ext JS组件的内联事件处理函数工作时,都须要使用thiskeyword来获取对应类的对象的应用。通常情况下,组件的事件处理程序的this指向的是该组件这个对象。隐藏,要解决问题。一些开发者会在构造函数或类的initComponent方法内使用一些全局变量来引用类,然后在内联处理中使用全局变量来获取对应的类对象。只是,这是错误的做法,我们赢遵循这里的约定。

  42. 尝试使用client缓存:本地存储、session存储、sqllite等等。假设使用HTML5,就能够将一些数据保持在client(不是cookie),并在再次浏览该页时使用这些数据。

    这样。就能够避免将一些不是必需的东西发送到server或数据库。在Ext JS,能够使用代理来处理这类缓存。

    在Ext JS中有两类代理:ClientProxy和ServerProxy。

    ClientProxy就是用来处理client缓存的。有下面三种类型的ClientProxy:

    • Ext.data.proxy.LocalStorage:LocalStorageProxy使用新的HTML5的localStorage来载入和保存数据到client浏览器。LocalStorage可在域中设置字段,这意味着关闭浏览器后再打开它,数据还在LocalStorage中。LocalStorage同意长期存储,此外还能够在全部浏览器的标签页或窗体中訪问它。


    • Ext.data.proxy.SessionStorage:SessionStorageProxy使用的是新的HTML5的SessionStorage API来载入和保持数据到client浏览器。SessionStorage设置的字段是基于窗体的。这意味着浏览器关闭后。数据也会丢失。即使站点在还有一个浏览器窗体依旧是打开的。SessionStorage的数据被局限于创建他的浏览器窗体中。

    • Ext.data.proxy.MemoryProxy:MemoryProxy是一个辅助性的代理。通常,它用来载入一些内联数据到存储。

      MemoryProxy的内容会在页面刷新后对视。它通经常使用来载入暂时数据。


    除了这些。一些浏览器。如chrome,还支持一些特殊类型的client数据,如SQLLite,它能够在client存储一些数据。因此,通过使用这些技术,能够用来提高应用程序的性能。

  43. 不要使用Array.isArray:Array.isArray(anyObject)方法用来推断anyObject是否一个数组对象。该方法仅仅能在Chrome中工作,不能在IE中工作。IE并不能识别该方法并会给出错误。

    可使用instanceof来替代该方法来达到同样的目的。

    instanceof方法既可在IE工作,也可在Chrome工作。

  44. 一定要注意日期格式:在解析日期的时候。要注意日期字符串的格式是否既支持IE。又支持chrom:
                                      var dateString = "03/20/2008";                                 
                                     var dateString = "2008/03/20";                                                 
                                     var dateString = "03-20-2008";                                  
                                     var dateString = "March 20, 2008";                                         
                                     var dateString = "Mar 20, 2008";                                              
                                     var dateString = "Oct 2, 2011";
    

    不要使用var dateString = "Oct/02/2011",IE不支持。在chrome中是支持的。我已经在应用程序修正了这个。



  45. 别忘了下面要点:下面是在将代码公布为产品时不应忘记的一些要点:

    没有跟随逗号
    即使仅仅有一行凝视,也要使用多行凝视来取代单行凝视
    没有调试的代码要留下凝视
    在预期的情况下,不要丢失不论什么分号
    不要在生产代码中使用console.log





作者会持续更新这篇文章。假设你有不论什么意见会反馈,可联系作者。




原文地址:https://www.cnblogs.com/yjbjingcha/p/7103557.html