Cómo mejorar el rendimiento en IE8 usando Dojo

He construido un RIA en una sola página. Estoy usando Dojo 1.7.2. La página contiene alrededor de 200 dijit/NumberSpinners y algunos TabContainers y TitlePanes. Por supuesto esto funciona perfectamente en todos los navegadores, excepto en Internet Explorer 8 que es el que utiliza la empresa del cliente.

En todos los navegadores, el análisis de toda la página tarda unos segundos, en IE8 fue de 2 minutos y lo reduje a 40 segundos siguiendo los siguientes consejos:

  • Usar compilación personalizada
  • Cree widgets programáticamente en lugar de declarativamente
  • Analice los widgets solo una vez que se muestran. (esto no acelera el análisis, solo hace que el usuario espere más mientras utilizando la aplicación en lugar de antes.)
  • Sustituir NumberSpinners por NumberTextBox (¡lo que redujo el tiempo de análisis a la mitad!)

¿Algún otro consejo? Podría intentar reutilizar los NumberSpinners y tirarlos cuando se vea un div, pero esto requiere que mi aplicación se reescriba bastante.

preguntado el 22 de mayo de 12 a las 18:05

1 Respuestas

La situación a la que se enfrenta es que se crean muchos nodos en el DOM y programáticamente. IE tiene un rendimiento deficiente para esto, siendo retenido por el motor javascript. ¡¿Ay, eh?!

Su objetivo es definir tanto como sea posible de antemano en lugar de anularlo durante el tiempo de ejecución. Con esto me refiero a establecer parámetros en los argumentos data-dojo-props/construcción. Esto se aplica especialmente a cosas como controladores onClick, etc. Lo lograrías haciendo algo así:

var MyConstruct = dojo.define("foo.MyConstruct", [ /* inheritance */ dijit.form.ValidationTextBox ], function() {
      // instead of setting properties during construct, preset those which are possible
      constraints: { min: 0, max: 100 },
      postMixInArguments: function() {
          this.inherited(arguments);    // call widget first
          if(this.constructParameter) ; // act on it
      },
      // implement any overrides you otherwise would need
      // and for minimal runtime overhead, redefine the private version, like _onBlur
      // copy the source and change what you need
      onBlur: function () {
          // an event override example
      }
});

Pero; ¿Por qué NumberSpinners > NumberTextBoxes se redujo en un 50 %? Esta es la razón por:

Cuadro de texto de plantilla

<div class="dijit dijitReset dijitInline dijitLeft" id="widget_${id}" role="presentation"
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class="dijitReset dijitInputInner" data-dojo-attach-point='textbox,focusNode' autocomplete="off"
            ${!nameAttrSetting} type='${type}'
    /></div
></div>

Girador de plantillas

<div class="dijit dijitReset dijitInline dijitLeft"
    id="widget_${id}" role="presentation"
    ><div class="dijitReset dijitButtonNode dijitSpinnerButtonContainer"
        ><input class="dijitReset dijitInputField dijitSpinnerButtonInner" type="text" tabIndex="-1" readonly="readonly" role="presentation"
        /><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton"
            data-dojo-attach-point="upArrowNode"
            ><div class="dijitArrowButtonInner"
                ><input class="dijitReset dijitInputField" value="&#9650;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
                    ${_buttonInputDisabled}
            /></div
        ></div
        ><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton"
            data-dojo-attach-point="downArrowNode"
            ><div class="dijitArrowButtonInner"
                ><input class="dijitReset dijitInputField" value="&#9660;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
                    ${_buttonInputDisabled}
            /></div
        ></div
    ></div
    ><div class='dijitReset dijitValidationContainer'
        ><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="&#935;" type="text" tabIndex="-1" readonly="readonly" role="presentation"
    /></div
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class='dijitReset dijitInputInner' data-dojo-attach-point="textbox,focusNode" type="${type}" data-dojo-attach-event="onkeypress:_onKeyPress"
            role="spinbutton" autocomplete="off" ${!nameAttrSetting}
    /></div
></div>

No hay mucho que se pueda hacer con la plantilla de TextBox para optimizarla, el único punto de entrada sería el parámetro ${type} que se establece mediante el reemplazo regular de exp a través de _getTypeAttr. en postMixInProps (antes de que _TemplatedMixin se ejecute y genere DOM), el valor se anula en 'texto' incluso si se especifica algo más. Aunque, no estoy seguro de cómo implicaría esto, uno podría querer quitar el focusNode + FocusMixin, pero no entraré en eso.

Hay un pequeño manejo peculiar en el dijit/form/MappedTextBox (que crea un oculto <input>, que contiene el valor 'verdadero' ver http://bugs.dojotoolkit.org/ticket/8660. Esto ha colocado un reemplazo de expresión regular en 'this.name' para solucionar problemas: omitir el atributo de nombre en su campo de entrada se encargará de eso (si es posible, use Id en su lugar).

Cuadro de texto de validación de plantilla

La razón principal para usar NumberTextBox sería la limitación de rango, ¿verdad? Para que se cargue ese módulo en particular, se realizan una serie de combinaciones, pero básicamente se basan en ValidationTextBox. Esto ofrece un .validate funcionalidad y muestra mensajes si es necesario. La nota anterior sobre la eliminación de focusmixin eliminará los mensajes, ya que actúan sobre los eventos onBlur.

Si tuviera que usar ValidationTextBox en lugar de NumberTextBox e implementar las comprobaciones de rango mediante una funcionalidad personalizada, creo que funcionaría de maravilla. Una gran cantidad de código evaluado se ejecuta sobre el cuadro de texto de validación para convertirlo en cuadros de texto numéricos, algunos de los cuales probablemente sean gastos generales en su caso.

<div class="dijit dijitReset dijitInline dijitLeft"
    id="widget_${id}" role="presentation"
    ><div class='dijitReset dijitValidationContainer'
        ><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="&#935; " type="text" tabIndex="-1" readonly="readonly" role="presentation"
    /></div
    ><div class="dijitReset dijitInputField dijitInputContainer"
        ><input class="dijitReset dijitInputInner" data-dojo-attach-point='textbox,focusNode' autocomplete="off"
            ${!nameAttrSetting} type='${type}'
    /></div
></div>

una anulación de muestra a la validación:

dijit.byId("validationTextBoxNodeId").validator = function(value, constraints){

    // Check that email has not been used yet.
    if(some-checks){
        return true;
    }else{
        return false;
    }
}

Respondido el 04 de junio de 12 a las 12:06

Wow, excelentes puntos y ejemplos elaborados, los revisaré la próxima semana. ¡Muchas gracias! - Innovar

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.