2011-04-04 12 views
11

Estoy usando jQuery Validate plugin 1.8.0 con jQuery 1.5. Funciona muy bien para formas pequeñas y medianas. Para formularios más grandes, el rendimiento se degrada significativamente (incluso en IE8 y FF4), lo que a veces provoca que el mensaje "la secuencia de comandos se ejecute demasiado lento". Parece que el complemento escanea todo el DOM dentro del formulario en busca de atributos y clases para validar, incluso si usted especificó reglas personalizadas. ¿Alguien sabe cómo apagar esto por completo? También hay una opción de ignorar, pero aún escanearía el DOM, omitiendo aquellos con el atributo ignorar.jQuery validar formularios grandes - secuencia de comandos ejecutándose lentamente

Esto es lo que ASP.NET genera, excepto que hay alrededor de 120 filas de datos. Paginar los resultados no es una opción, desafortunadamente.

<table id="GridView1"> 
    <tbody> 
     <tr> 
      <th scope="col">Header 1</th> 
      <th scope="col">Header 2</th> 
      <th scope="col">Header 3</th> 
      <th scope="col">Header 4</th> 
      <th scope="col">Header 5</th> 
      <th scope="col">Header 6</th> 
      <th style="width: 60px; white-space: nowrap" scope="col">Header 7</th> 
      <th style="width: 60px; white-space: nowrap" scope="col">Header 8</th> 
     </tr>   
     <tr class="gridRow" jquery1507811088779756411="3"> 
      <td style="width: 50px" align="middle"> 
       <span id="GridView1_ctl03_Label1">XXX</span> 
      </td> 
      <td> 
       <span id="GridView1_ctl03_Label2">YYY</span> 
      </td> 
      <td style="width: 50px" align="middle"> 
       <span id="GridView1_ctl03_Label3">ZZZ</span> 
      </td> 
      <td align="middle"> 
       <select style="width: 70px" id="GridView1_ctl03_Dropdown4" name="GridView1$ctl03$Dropdown4"> 
        <option selected value="Y">Y</option> 
        <option value="N">N</option> 
       </select> 
      </td> 
      <td style="width: 50px" align="middle"> 
       <input id="GridView1_ctl03_hidId1" value="100" type="hidden" name="GridView1$ctl03$hidId1" /> 
       <input id="GridView1_ctl03_hidId2" value="100" type="hidden" name="GridView1$ctl03$hidId2" /> 
       <input id="GridView1_ctl03_hidId3" value="100" type="hidden" name="GridView1$ctl03$hidId3" /> 
       <input id="GridView1_ctl03_hidId4" value="100" type="hidden" name="GridView1$ctl03$hidId4" /> 
       <select style="width: 40px" id="GridView1_ctl03_Dropdown5" name="GridView1$ctl03$Dropdown5"> 
        <option selected value="A">A</option> 
        <option value="B">B</option> 
       </select> 
      </td> 
      <td style="width: 50px" align="middle"> 
       <span id="GridView1_ctl03_Label6">101</span> 
      </td> 
      <td align="middle"> 
       <input style="width: 60px" id="GridView1_ctl03_Textbox8" class="date required" 
        title="Please enter a valid start date." type="text" name="GridView1$ctl03$Textbox8" 
        jquery1507811088779756411="122" /> 
      </td> 
      <td align="middle"> 
       <input style="width: 60px" id="GridView1_ctl03_Textbox9" class="date" 
        title="Please enter a valid end date." type="text" name="GridView1$ctl03$Textbox9" 
        jquery1507811088779756411="123" /> 
      </td> 
     </tr> 
    </tbody> 
</table> 
+0

Muéstranos el código, un enlace directo, o una [demo] (http://jsfiddle.net). ¿Qué tan grande es esta forma? –

+0

Puse una muestra de código (los nombres de datos y control cambiaron para proteger a los inocentes).Hay aproximadamente 120 filas de datos, y realmente solo estoy validando los campos de fecha. Toma 8-9 segundos para validar el formulario en IE8. – Jeff

Respuesta

0

Necesitamos más código para ayudarlo. Pero atravesar objetos DOM es una operación pesada. Quizás para esas formas grandes quieras usar otro enfoque. Si está utilizando una gran cantidad de combos y campos de texto, puede adjuntar un controlador de eventos (en el foco perdido) para que pueda guardar el valor en un objeto javascript y luego utilizar este objeto para obtener los datos.

+0

Atravesar el DOM es muy pesado, no creo que el complemento de validación deba hacer eso si está especificando reglas personalizadas. Podría pasar la validación en este formulario, pero quería que fuera coherente con el resto de la aplicación. Estoy pensando que debería personalizar el script de validación por mi cuenta. – Jeff

9

He estado luchando con este problema también. Personalizando parte de la validación, pude reducir el tiempo de validación en IE8 para 80 elementos de validación de 4100ms a 192ms. Publicaré mis hallazgos aquí con la esperanza de que otros puedan beneficiarse, y también con la esperanza de que algún experto en jquery-validate encuentre un problema con mi código.

Aquí hay algunas cosas que he encontrado útil:

  1. asegurarse de que usted no tiene los atributos de validación en cualquier cosa que en realidad no necesita validar. Tuve algunos misteriosamente mostrados en los elementos, no estoy seguro por qué, pero codifiqué datos validos = falsos en ellos en mi archivo .cshtml para evitar esto.
  2. Defina su propio método para validar el formulario. El construido en jQuery hace un par de cosas muy lentamente, y es probable que no necesite toda la flexibilidad que proporciona. Aquí está el mio: usar esto hizo una GRAN diferencia (se llama subconjunto porque mi formulario está dividido en pestañas y llamo esto a cada tabulador individualmente a medida que el usuario avanza).

    jQuery.validator.prototype.subset = function (container, validateHiddenElements) { 
        var ok = true; 
        var validator = this; 
    
        // Performance hack - cache the value of errors(), and temporarily patch the function to return the cache 
        // (it is restored at the end of this function). 
        var errors = this.errors(); 
        var errorsFunc = this.errors; 
        this.errors = function() { return errors; }; 
    
        $(container.selector + " [data-val=true]").each(function() { 
    
         !this.name && validator.settings.debug && window.console && console.error("%o has no name assigned", this); 
    
         var tagName = this.tagName.toLowerCase(); 
         if (tagName == "input" || tagName == "select" || tagName == "textarea") { 
          var $this = $(this); 
    
          if (!$this.hasClass('doNotValidate') && 
           (validateHiddenElements || $this.is(':visible'))) { 
    
           if (!validator.element($this)) ok = false; 
    
          } 
         } 
        }); 
    
        this.errors = errorsFunc; 
    
        return ok; 
    }; 
    
  3. Defina su propio método showErrors en validator.settings. El built-in crea espacios de mensajes de error para cada entrada validable incluso cuando no hay ningún error para mostrar. Esto se vuelve bastante lento si tiene muchos de estos, por lo que puede agregar algo de lógica para evitar esto. Esta es la mía:

    function showErrorsOverride() { 
        var anyElementsNeedUpdate = false; 
        for (var i = 0; i < this.errorList.length; i++) { 
         if (!$(this.errorList[i].element).hasClass(this.settings.errorClass)) { 
         anyElementsNeedUpdate = true; 
         } 
        } 
        for (var i = 0; i < this.successList.length; i++) { 
         if ($(this.successList[i]).hasClass(this.settings.errorClass)) { 
          anyElementsNeedUpdate = true; 
         } 
        } 
    
    
        if (anyElementsNeedUpdate) 
        { 
         // show the usual errors (defaultShowErrors is part of the jQuery validator) 
         this.defaultShowErrors(); 
        } 
    } 
    
+1

¿Dónde debería poner esto? – eddy

+0

Simplemente agregando algunos 'data-val = false' en ciertas listas de selección hizo una gran diferencia para mí. Tiempo de carga de 34 segundos a solo 8. – wf4

9

Un poco tarde a la fiesta, pero para cualquier persona interesada - similar a la respuesta de Joe, me pareció que al desactivar el ajuste de los defaultShowErrors éxito() la función ayuda a salir un poco. Todo lo que parece hacer es ocultar la etiqueta de error para los campos válidos, y si no tiene ninguna etiqueta de error, no es necesario que se sobrecargue. Sped mi formulario con 55 campos de ~ 1.8 segundos a ~ 260ms en IE8.

$(document).ready(function() 
{ 
    $("form").each(function() 
    { 
     $(this).data("validator").settings.success = false; 
    }) 
}); 
+0

Quería confirmar a otros que esta configuración mejoró significativamente mi rendimiento. Estoy validando miles de elementos y mi rendimiento (especialmente en Firefox) mejoró de más de 80 segundos a aproximadamente 15 segundos. IE 11 mostró una mejoría similar. Decepcionante, Chrome era TERRIBLE. Recibió continuamente el mensaje "Kill Page" (que a partir de hoy es un error conocido). Muy, muy decepcionado con las versiones más nuevas de Chrome para otros desarrolladores web también. – Rob

+0

Hola, incluso más tarde en la fiesta: estoy luchando con el mismo problema: ¿dónde debería poner este fragmento de código? Traté de ponerlo directamente después de cargar el Javascript javascript, pero parece llegar tarde. – Stefan

+1

@Stefan Eche un vistazo a [este enlace] (http://stackoverflow.com/a/17659169/1087945). – hawkke

0

Tuvimos problemas similares con la forma grande pero encontramos la siguiente solución. Ahora nuestras formas grandes (> 600 entradas) validan en ~ 10ms.

He publicado la respuesta aquí: https://stackoverflow.com/a/23132844/1821717

Cuestiones relacionadas