Mejora anidada para los bucles para la creación de submarino -- javascript campo con jquery camp codereview Relacionados El problema

Improving nested for loops for sub menu creation


7
vote

problema

Español

Tengo un bucle anidado que crea una caída con 3 niveles. Funciona bien en los navegadores modernos, pero en IE8 se cuelga y toma varios segundos cuando incluso hay un volumen moderado de datos.

Crea una lista de editores, cuando hago clic en un editor, obtengo a los autores de los editores, haga clic en un autor que recibo los años que están publicados.

Estoy buscando una forma de optimizar esto para reducir el tiempo que lleva a ejecutar en IE.

¿Alguna idea?

  function createDropDown() {                 var target = $('#dropdownMenu');         for (var i = 0; i < data.genres.length; i++) {                 var genreval = data.genres[i].genre;                 for (var j = 0; j < data.genres[i].publishers.length; j++) {                         var publisherval = data.genres[i].publishers[j].publisher;                         if (typeof app.cache.publisher[publisherval] == 'undefined') {                                 target.append('<li class="publisher" data-value="' + publisherval + '"><a href="#" class="nextmenu">' + publisherval + '</a><ul class="sub-menu" data-title="publishers"></ul></li>');                                 app.cache.publisher[publisherval] = {                                         'ul': target.find('>.publisher[data-value="' + publisherval + '"]>.sub-menu'),                                         'author': {}                                 };                          }                                 var ulauthors = app.cache.publisher[publisherval].ul;                                 for (var k = 0; k < data.genres[i].publishers[j].authors.length; k++) {                                         var authorval = data.genres[i].publishers[j].authors[k].author + ' (' + genreval + ')';                                         var author_val = data.genres[i].publishers[j].authors[k].author;                                         var originalgenre = data.genres[i].publishers[j].authors[k].originalgenre;                                         if (typeof app.cache.publisher[publisherval].author[authorval] == 'undefined') {                                                 ulauthors.append('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a><ul class="sub-menu" data-title="authors"></ul></li>');                                                 app.cache.publisher[publisherval].author[authorval] = ulauthors.find('>.author[data-value="' + authorval + '"]>.sub-menu');                                                                      }                                                                     var ulyears = app.cache.publisher[publisherval].author[authorval];                                                                     var gItems = "";                                                                     for (var m = 0; m < data.genres[i].publishers[j].authors[k].authorYears.length; m++) {                                                                             var yearval = data.genres[i].publishers[j].authors[k].authorYears[m];                                                                             var year = ulyears.find('.year[data-value="' + yearval + '"]');                                                                             if (year.size() == 0) {                                                                                     var id = ++count;                                                                                     gItems+='<li class="year" data-value="' + yearval + '"><a id="selyear' + id + '" class="addItem" data-id="' + id + '" data-originalgenre ="' + originalgenre + '"data-year="' + yearval + '" data-publisher="' + publisherval + '" data-author="' + author_val '">' + yearval + '</a></li>';                                                                             }                                                                     }                                         ulyears.append(gItems);                                 };                 };         };     }   

Código editado que no adjunta a los autores:

  if (typeof app.cache.publisher[publisherval].author[authorval] == 'undefined') { app.cache.publisher[publisherval].author[authorval] = $('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a><ul class="sub-menu" data-title="authors"></ul></li>').children('ul').appendTo(ulauthors); }   
Original en ingles

I have a nested loop which creates a drop down with 3 levels. Works fine on modern browsers but on IE8 it hangs and takes several seconds when there's even a moderate volume of data.

It creates a list of publishers, when I click a publisher I get that publishers authors, click an author I get the years they're published.

I'm looking for a way of optimizing this to reduce the time it takes to run in IE.

Any ideas?

function createDropDown() {                 var target = $('#dropdownMenu');         for (var i = 0; i < data.genres.length; i++) {                 var genreval = data.genres[i].genre;                 for (var j = 0; j < data.genres[i].publishers.length; j++) {                         var publisherval = data.genres[i].publishers[j].publisher;                         if (typeof app.cache.publisher[publisherval] == 'undefined') {                                 target.append('<li class="publisher" data-value="' + publisherval + '"><a href="#" class="nextmenu">' + publisherval + '</a><ul class="sub-menu" data-title="publishers"></ul></li>');                                 app.cache.publisher[publisherval] = {                                         'ul': target.find('>.publisher[data-value="' + publisherval + '"]>.sub-menu'),                                         'author': {}                                 };                          }                                 var ulauthors = app.cache.publisher[publisherval].ul;                                 for (var k = 0; k < data.genres[i].publishers[j].authors.length; k++) {                                         var authorval = data.genres[i].publishers[j].authors[k].author + ' (' + genreval + ')';                                         var author_val = data.genres[i].publishers[j].authors[k].author;                                         var originalgenre = data.genres[i].publishers[j].authors[k].originalgenre;                                         if (typeof app.cache.publisher[publisherval].author[authorval] == 'undefined') {                                                 ulauthors.append('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a><ul class="sub-menu" data-title="authors"></ul></li>');                                                 app.cache.publisher[publisherval].author[authorval] = ulauthors.find('>.author[data-value="' + authorval + '"]>.sub-menu');                                                                      }                                                                     var ulyears = app.cache.publisher[publisherval].author[authorval];                                                                     var gItems = "";                                                                     for (var m = 0; m < data.genres[i].publishers[j].authors[k].authorYears.length; m++) {                                                                             var yearval = data.genres[i].publishers[j].authors[k].authorYears[m];                                                                             var year = ulyears.find('.year[data-value="' + yearval + '"]');                                                                             if (year.size() == 0) {                                                                                     var id = ++count;                                                                                     gItems+='<li class="year" data-value="' + yearval + '"><a id="selyear' + id + '" class="addItem" data-id="' + id + '" data-originalgenre ="' + originalgenre + '"data-year="' + yearval + '" data-publisher="' + publisherval + '" data-author="' + author_val '">' + yearval + '</a></li>';                                                                             }                                                                     }                                         ulyears.append(gItems);                                 };                 };         };     } 

Edited Code which doesnt append the authors:

if (typeof app.cache.publisher[publisherval].author[authorval] == 'undefined') { app.cache.publisher[publisherval].author[authorval] = $('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a><ul class="sub-menu" data-title="authors"></ul></li>').children('ul').appendTo(ulauthors); } 
     
   
   

Lista de respuestas

8
 
vote
vote
La mejor respuesta
 

Formato

Encontré esto extremadamente difícil de leer. La sangría en particular es inconsistente. Sospecho altamente que esto se debe a que su código contiene pestañas y espacios mixtos. (StackExchange convierte silenciosamente las pestañas en cuatro espacios. Si este no es el caso, ignore esta sección).

No quiero comenzar una guerra santa o nada, pero hay tres campamentos principales aquí.

  1. sangría exclusivamente con pestañas. Esto es agradable cuando se usa editores de texto con un ancho configurable para pestañas. También puede acelerar marginalmente un sitio, pero eso es solo si aún no está eliminando el espacio en blanco antes de enviarlo al cliente. También es insignificante en la era de gzip .

  2. sangría exclusivamente con espacios. Esto garantiza que el código se verá igual para todos. Sin embargo, como no es configurable, si te gustan ocho espacios y alguien más le gustan dos espacios, no pueden simplemente hacer que suceda con un escenario; deberán reemplazar en el archivo.

  3. Mixed: Niveles de indentación Use las pestañas, pero la alineación se realiza con espacios. Este es el estilo que yo uso personalmente.

a un lado : Los punto y coma típicamente no son necesarios después de los tirantes. Está utilizando un bloque de código para A para lazo, no una expresión de función.

Naming

  • No veo ningún punto en nombrar una variable genreval ; solo genre es suficiente.
  • La convención dicta que las variables de objetos jQuery están prefijados con un $ .
  • Creo que es particularmente confuso tener authorval y author_val . En todo caso, tendría author_val → author y authorval → authorWithGenre o algo ... Realmente no sé cómo nombraría esto. ¿Es fundamental que se distingan los géneros de un autor?
  • TIENE app.cache.publisher[].ul8 y app.cache.publisher[].author[] Tanto los objetos jquery para un genreval0 . Esto es inconsistente. Podría preferir cada elemento de genreval1 para ser un objeto con solo la tecla genreval2 , es decir, genreval3 .

Performance

Parece que eres genreval4 Ing un elemento e inmediatamente realizando un genreval5 para ello. Esto es increíblemente inútil. Solo puede usar genreval6 en su lugar.

Puedo pensar de dos maneras; Uno crea dos objetos y usa dos genreval7 s, mientras que uno realiza un 99887776655443318 consulta. Escribí un JSPERF rápido y sucio . El genreval9 consulta se ejecuta más rápido; Tu original es 91% más lento.

  genre0  
 

Formatting

I found this exceedingly difficult to read. The indentation in particular is inconsistent. I highly suspect that this is because your code contains mixed tabs and spaces. (StackExchange silently converts tabs into four spaces. If this is not the case, please ignore this section.)

I don't want to start a holy war or anything, but there are three main camps here.

  1. Indent exclusively with tabs. This is nice when using text editors with a configurable width for tabs. It also can marginally speed up a site, but that's only if you aren't already stripping out whitespace before sending to client. It's also negligible in the era of gzip.

  2. Indent exclusively with spaces. This guarantees that the code will look the same for everyone. Since it isn't configurable, though, if you like eight spaces and someone else likes two spaces, they can't just make it happen with a setting; they'll need to do a replace on the file.

  3. Mixed: indentation levels use tabs, but alignment is done with spaces. This is the style I personally use.

Aside: Semicolons are typically not necessary after braces. You're using a code block for a for loop, not a function expression.

Naming

  • I don't see any point in naming a variable genreval; just genre is enough.
  • Convention dictates that jQuery object variables are prefixed with a $.
  • I think that it's particularly confusing to have authorval and author_val. If anything, I'd have author_val xe2x86x92 author and authorval xe2x86x92 authorWithGenre or something... I really don't know how I'd name this. Is it critical that an author's genres are distinguished?
  • You have app.cache.publisher[].ul and app.cache.publisher[].author[] both being jQuery objects for a ul. This is inconsistent. I might prefer each element of author[] to be an object with just the key ul, i.e. author[] = { 'ul': ... };.

Performance

It looks like you're appending an element and immediately performing a find for it. This is incredibly wasteful. You can just use appendTo instead.

I can think of two ways; one creates two objects and uses two appendTos, while one performs a children query. I wrote a quick-and-dirty jsPerf. The children query runs the fastest; your original is 91% slower.

// children app.cache.publisher[publisherval].author[authorval] = {     'ul': $('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a><ul class="sub-menu" data-title="authors"></ul></li>').children('ul').appendTo(ulauthors) } // double append app.cache.publisher[publisherval].author[authorval] = {     'ul': $('<ul class="sub-menu" data-title="authors"></ul>').appendTo($('<li class="author" data-value="' + authorval + '"><a href="#" class="nextmenu">' + authorval + '</a></li>').appendTo(ulauthors)) } 
 
 
         
         
8
 
vote

Hay algunas cosas que puede hacer para mejorar su código JavaScript.

Por ejemplo, puede guardar el elemento que está utilizando en cada bucle:

  genre1  

Cada vez que use un objeto como genre2 , el navegador tiene que caminar a través de todas las propiedades, desacelerando el proceso.

Sus bucles están revisando la longitud de la matriz cada iteración. Esto será más rápido:

  genre3  

Una biblioteca de microtemplate le ayudará a generar mucho la HTML, pero de todos modos, sería mejor si genera la cadena completa y agrega una vez al domdom, hay muchas operaciones adjuntares que requieren algún tiempo.

En general, intentaría usar una solución dinámica: solo generar el primer nivel del menú y luego agregar dinámicamente los submenús en el cursor.

 

There are a few things you can do to improve your JavaScript code.

For example, you can save the element you are using in each loop:

var currentPuiblisher = data.genres[i].publishers[j] 

Every time you use a object like data.genres[i].publishers[j], the browser has to walk through every property, slowing down the process.

Your loops are checking the length of the array every iteration. This will be faster:

for (var k = 0, authLength = data.genres[i].publishers[j].authors.length; k < authLength; k++) 

A microtemplate library would help you a lot generating the HTML, but anyway it would be better if you generate the full string and append once to the domDOM, there are a lot of append operations that require some time.

In general, I would try to use a dynamic solution: just generating the first level of the menu, and then dynamically add the submenus on hover.

 
 

Relacionados problema

1  Manipulador de eventos repetitivos para un control de interfaz de usuario de la UI  ( Repetitive event handler for a toggling ui control ) 
Siento que este tipo de código podría haber sido escrito más elegante, especialmente con las enormes afirmaciones de IF / ODS. ¿Alguien puede ayudarme a rompe...

2  Limpiando una galería de imágenes rotativas  ( Cleaning up a rotating image gallery ) 
He creado una pequeña galería de imágenes para la web. Me propuse querer 3 cosas. 1. Toda la galería tenía una capacidad de respuesta a nivel básica. 2. La ga...

3  Página web basada en una muestra de un libro  ( Web page based on a sample from a book ) 
He creado una página web basada en una muestra de un libro. Funciona bien, pero parece haber sido demasiado complicado. dt4 ¿Es posible mejorar la clari...

3  Función de estilo sortable jquery  ( Jquery sortable style function ) 
Esta es una función de clasificación básica escrita en jQuery que mueve los elementos en la DOM alrededor para crear espacios vacíos para un gotpable (). Como...

8  Escribiendo un widget de jquery: plantilla  ( Writing a jquery widget templating ) 
Estoy haciendo mi primer mayor desarrollo de jQuery. Es un widget para eventos recurrentes, y es como una bestia bastante compleja. El código completo está di...

5  Función de movimiento para un juego  ( Move function for a game ) 
Tengo una función PackageSubpackageSubpackageName6 en este juego que estoy haciendo. Funciona bien, pero me gustaría reducir un poco su tamaño. PackageSu...

1  Actualización de una página web de DRUPAL con contenido basado en texto ingresado  ( Updating a drupal web page with content based on inputted text ) 
La intención es actualizar una página web de drupal existente con contenido basado en texto ingresado en un cuadro de texto. La página existente muestra dat...

2  Animaciones de la línea de tiempo  ( Timeline animations ) 
Hice recientemente esta línea de tiempo del campus para mi universidad. Al ver la línea de tiempo en un dispositivo móvil (no una tableta), la barra de nave...

3  Construyendo una tabla HTML utilizando JavaScript  ( Building an html table using javascript ) 
¿Una forma más legible para hacer esto? renderHtmlTable(function(tableItems) { var tableArray,_i,item,_len; tableArray = ['<table id = sampleTable ><...

1  Sube y arrastra la imagen dentro de una imagen de máscara  ( Upload and drag the image inside a mask image ) 
Estoy permitiendo a los usuarios subir y arrastrar imágenes con este código. Dame una revisión de esto. Codepen $part = '@CRC := MD5(CONCAT_WS('#', COA...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos