2016-01-25 2 views
3

В настоящее время я извлекаю много информации из базы данных и хотел бы отображать эту информацию в виде миниатюр на сайте. Каждая строка, собранная из базы данных, содержит изображение и некоторую другую информацию, которая появляется в миниатюре.Медленное создание divs с использованием innerHTML и + =

Когда информация собирается ли использовать функцию под названием printAllMini, который печатает все дивы в контейнер с помощью printMini для каждой строки информации.

printAllMini = function() { 
 
    console.log("PRINTING!"); 
 
    document.getElementById("mini_blocks").innerHTML = ""; 
 
    for (var i = 0; i < docs.length; i++) { 
 
\t var object = docs[i]; 
 
\t printMini(object.id, object.arrived, object.booked, object.verification, object.org, object.price, object.stax, object.pic); 
 
\t console.log(i); 
 
    } 
 
    console.log("DONE!"); 
 
} 
 

 
printMini = function(id, arrived, booked, verification, org, price, stax, pic) { 
 
    if (verification != "-") { 
 
\t // So that no string is empty 
 
\t if (id == "") { id = "-"; } 
 
\t if (arrived == "") { arrived = "-"; } 
 
\t if (booked == "") { booked = "-"; } 
 
\t if (verification == "") { verification = "-"; } 
 
\t if (org == "") { org = "-"; } 
 
\t if (price == "") { price = "-"; } 
 
\t if (stax == "") { stax = "-"; } 
 
\t document.getElementById("mini_blocks").innerHTML += '<div class="mini" id="\'' + id + '\'" onclick="changeInfo(\'' + arrived + '\', \'' + booked + '\', \'' + verification + '\', \'' + org + '\', \'' + price + '\', \'' + stax + '\', \'' + id + '\'), getPDF2(\'' + id + '\')"> <div class="mini_header"> <table class="mini_table"> <tr> <td align="left"> <b>Inkommen</b> </td> <td align="right"> <b>ID</b> </td> </tr> <tr> <td align="left">' + arrived + '</td> <td align="right">' + id + '</td> </tr> </table> </div> <div class="mini_img"> <img src="data:image/jpeg;base64,' + pic + '"> </div> <div class="mini_footer"> <table class="mini_table"> <tr> <td align="left"> <b>Bokförd</b> </td> <td align="right"> <b>Verifikat</b> </td> </tr> <tr> <td align="left">' + booked + '</td> <td align="right">' + verification + '</td> </tr> </table> </div> </div>'; 
 
    } 
 
    else { 
 
\t document.getElementById("mini_blocks").innerHTML += '<div class="mini" id="\'' + id + '\'" onclick="changeInfo(\'' + arrived + '\', \'' + booked + '\', \'' + verification + '\', \'' + org + '\', \'' + price + '\', \'' + stax + '\', \'' + id + '\'), getPDF2(\'' + id + '\')"> <div class="mini_header2"> <table class="mini_table"> <tr> <td align="left"> <b>Inkommen</b> </td> <td align="right"> <b>ID</b> </td> </tr> <tr> <td align="left">' + arrived + '</td> <td align="right">' + id + '</td> </tr> </table> </div> <div class="mini_img"> <img src="data:image/jpeg;base64,' + pic + '"> </div> <div class="mini_footer2"> </div> </div>'; 
 
    } 
 
}

Проблема:

Это, однако, очень медленно и занимает свыше 45 секунд, чтобы закончить. Там, кажется, что это имеет отношение к линии:

document.getElementById("mini_blocks").innerHTML += '<div'>; 

... как это занимает больше времени и больше времени для дивы будут созданы. Первые 10 divs создаются в течение первой секунды, но ближе к концу происходит около одного div, созданного за секунду. Он становится все медленнее и медленнее.

Этот GIF показывает первые несколько секунд процесса и при каждом DIV делается: GIF

Я попытался (заметьте + знак перед =) document.getElementById("mini_blocks").innerHTML += '<div>'

... который намного быстрее, он делает то же самое, но заменяет все предыдущие div, так что я получаю только один div. Это почти мгновенно!

Я также заметил, что ни один из divs не появляется до тех пор, пока все divs не будут выполнены, и я не знаю, почему.

Актуальные вопросы:

  1. Есть ли что-то, что делает + = метод медленно при создании дивы?
  2. Есть ли причина, по которой ни один из divs не появляется до самого конца?
  3. Я новичок в веб-программировании. Есть ли лучшие способы сделать то же самое?
+2

Если это так медленно - почему бы вам не сохранить строку сначала (используя глобальную переменную) и установить только '.innerHTML' после завершения цикла? – freefaller

+0

Я чувствую себя глупо, что не пробовал это самостоятельно. Благодаря! – Logic

ответ

1

Вместо того, чтобы искать document.getElementById("mini_blocks") и затем установить .innerHTML на каждой итерации цикла - попробуйте хранить значение в глобальной переменной (например, я здесь с printMiniResult) и установить .innerHTML только один раз ...

var printMiniResult = ""; 
 

 
printAllMini = function() { 
 
    console.log("PRINTING!"); 
 
    for (var i = 0; i < docs.length; i++) { 
 
\t var object = docs[i]; 
 
\t printMini(object.id, object.arrived, object.booked, object.verification, object.org, object.price, object.stax, object.pic); 
 
\t console.log(i); 
 
    } 
 
    document.getElementById("mini_blocks").innerHTML = printMiniResult; 
 
    console.log("DONE!"); 
 
} 
 

 
printMini = function(id, arrived, booked, verification, org, price, stax, pic) { 
 
    if (verification != "-") { 
 
\t // So that no string is empty 
 
\t if (id == "") { id = "-"; } 
 
\t if (arrived == "") { arrived = "-"; } 
 
\t if (booked == "") { booked = "-"; } 
 
\t if (verification == "") { verification = "-"; } 
 
\t if (org == "") { org = "-"; } 
 
\t if (price == "") { price = "-"; } 
 
\t if (stax == "") { stax = "-"; } 
 
\t printMiniResult += '<div class="mini" id="\'' + id + '\'" onclick="changeInfo(\'' + arrived + '\', \'' + booked + '\', \'' + verification + '\', \'' + org + '\', \'' + price + '\', \'' + stax + '\', \'' + id + '\'), getPDF2(\'' + id + '\')"> <div class="mini_header"> <table class="mini_table"> <tr> <td align="left"> <b>Inkommen</b> </td> <td align="right"> <b>ID</b> </td> </tr> <tr> <td align="left">' + arrived + '</td> <td align="right">' + id + '</td> </tr> </table> </div> <div class="mini_img"> <img src="data:image/jpeg;base64,' + pic + '"> </div> <div class="mini_footer"> <table class="mini_table"> <tr> <td align="left"> <b>Bokförd</b> </td> <td align="right"> <b>Verifikat</b> </td> </tr> <tr> <td align="left">' + booked + '</td> <td align="right">' + verification + '</td> </tr> </table> </div> </div>'; 
 
    } 
 
    else { 
 
\t printMiniResult += '<div class="mini" id="\'' + id + '\'" onclick="changeInfo(\'' + arrived + '\', \'' + booked + '\', \'' + verification + '\', \'' + org + '\', \'' + price + '\', \'' + stax + '\', \'' + id + '\'), getPDF2(\'' + id + '\')"> <div class="mini_header2"> <table class="mini_table"> <tr> <td align="left"> <b>Inkommen</b> </td> <td align="right"> <b>ID</b> </td> </tr> <tr> <td align="left">' + arrived + '</td> <td align="right">' + id + '</td> </tr> </table> </div> <div class="mini_img"> <img src="data:image/jpeg;base64,' + pic + '"> </div> <div class="mini_footer2"> </div> </div>'; 
 
    } 
 
}


в качестве дополнительного изменения (как предложено в ANSW er от vol7ron), вы можете использовать массив вместо конкатенации строк. Как говорит vol7ron, это будет намного более эффективно.

Значит, у вас есть что-то подобное ...

var printMiniResult = []; 

printAllMini = function() { 
    ... 
    document.getElementById("mini_blocks").innerHTML = printMiniResult.join(""); 
    ... 
} 

printMini = function(id, arrived, booked, verification, org, price, stax, pic) { 
    ... 
    printMiniResult.push(...); 
    ... 
} 
2
  1. Есть ли что-то, что делает + = метод медленно при создании дивы?

Да, но не только DIVs. Конкатенация строк является дорогостоящей и, как правило, дает плохую производительность. Вы начинаете замечать эту производительность, когда строка растет в длину или вы выполняете больше операций (конкатенаций).

  1. Есть ли причина, по которой ни один из divs не появляется до самого конца?

Объясните.

  1. Я новичок в веб-программировании. Есть ли лучшие способы сделать то же самое?

Вы можете использовать различные методы клонирования объектов, или только создавая строку один раз. Если вы хотите получить лучшие интерфейсные решения, вы должны посмотреть веб-фреймворки/библиотеки, такие как React или Angular.

Примером того, как улучшить использование кода, является отказ от конкатенации строк в цикле путем построения массива. Затем вы можете объединить все элементы массива, присоединившись к пустой строке: (например, ['begin','end'].join(''))

+0

Хорошая идея с массивом - вы не возражаете, что я зажимаю это и включаю его в качестве дополнительной части моего ответа? – freefaller

+1

@freefaller вперед. Этот ответ скорее является комментарием, в котором потребуется слишком много строк (я, вероятно, удалю после внесения изменений) – vol7ron

1

1) Да, есть. DOM пересчитывается каждый раз, когда вы воссоздаете элемент. Конкатенация длинных строк может занять некоторое время.

2) Сначала выполняется JavaScript, после чего отображается страница. Для этих задач браузер имеет только один поток.

3) Да, есть лучшие способы. Create elements и append или insert их. Обычно это больше кода, но быстрее.

Если вам сложно избавиться от строк для создания HTML-кода, используйте insertAdjacenHTML вместо innerHTML. Это быстрее, потому что оно не воссоздает элементы. Также, если это возможно, создайте HTMLString как можно большую часть и поместите только одну строку в DOM, что значительно сократит время повторного вычисления.

1

1: В строке javascript есть immutable. Поэтому каждый раз, когда вы изменяете строку, вы фактически создаете копию строки и добавляете к ней свои изменения. По мере роста строки это может занять много времени.

2: браузер не будет отображать HTML, пока ваш javascript не завершит выполнение. Вы можете обработать несколько разделов, затем получить контроль и использовать таймаут для продолжения обработки.

3: Не создавайте HTML, используя массивную строку. Я бы рекомендовал использовать подход, основанный на шаблонах. Возможно, вы захотите изучить Reactjs или Angular. В противном случае используйте методы dom для создания ваших узлов и добавления их в dom.