使用innerHTML和+ =

时间:2016-01-25 18:05:01

标签: javascript html innerhtml

我目前正在从数据库中检索大量信息,并希望将此信息显示为网站上的微缩模型。从数据库收集的每一行都包含一个图像和一些显示在缩略图中的其他信息。

收集信息后,我使用名为 printAllMini 的函数,该函数使用 printMini 为每行信息将所有div打印到容器中。

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

printMini = function(id, arrived, booked, verification, org, price, stax, pic) {
    if (verification != "-") {
	// So that no string is empty
	if (id == "") { id = "-"; }
	if (arrived == "") { arrived = "-"; }
	if (booked == "") { booked = "-"; }
	if (verification == "") { verification = "-"; }
	if (org == "") { org = "-"; }
	if (price == "") { price = "-"; }
	if (stax == "") { stax = "-"; }
	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 {
	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'>;

...因为创建div需要更长时间。前10个div在第一秒内创建,但到最后每秒创建一个div。它变得越来越慢。

此gif显示了该过程的前几秒以及每个div完成的时间:GIF

我试过了(注意+前面的+标志=) document.getElementById("mini_blocks").innerHTML += '<div>'

...这要快得多,它做同样的事情但是替换了所有前面的div,所以我最终得到一个div。这几乎是瞬间的!

我也注意到在所有div都完成之前没有任何div出现,我不明白为什么。

实际问题:

  1. 创建div时是否存在使+ =方法变慢的原因?
  2. 为什么没有一个div出现在最后?
  3. 我是网络编程的新手。是否有更好的方法来做同样的事情?

4 个答案:

答案 0 :(得分:2)

  
      
  1. 创建div时是否存在使+ =方法变慢的原因?
  2.   

是的,但不仅仅是DIV。字符串连接很昂贵,并且通常会产生糟糕的性能。当字符串长度增加时,或者执行更多操作(连接)时,您会开始注意到这种性能。

  
      
  1. 为什么没有一个div出现在最后?
  2.   

解释

  
      
  1. 我是网络编程的新手。是否有更好的方法来做同样的事情?
  2.   

您可以使用各种克隆对象的技术,或仅创建一次字符串。如果您想进入更好的前端解决方案,您应该查看Web框架/库,例如React或Angular。

如何改进使用代码的一个示例是通过构建数组来放弃循环中的字符串连接。然后,您可以通过连接空字符串来连接数组的所有元素:(例如['begin','end'].join('')

答案 1 :(得分:1)

不要在循环的每次迭代中查找document.getElementById("mini_blocks")然后设置.innerHTML - 而是尝试将值存储在全局变量中(例如我在这里使用printMiniResult)并设置.innerHTML只是一次......

var printMiniResult = "";

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

printMini = function(id, arrived, booked, verification, org, price, stax, pic) {
    if (verification != "-") {
	// So that no string is empty
	if (id == "") { id = "-"; }
	if (arrived == "") { arrived = "-"; }
	if (booked == "") { booked = "-"; }
	if (verification == "") { verification = "-"; }
	if (org == "") { org = "-"; }
	if (price == "") { price = "-"; }
	if (stax == "") { stax = "-"; }
	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 {
	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>';
    }
}

作为一个额外的更改(由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)

1)是的。每次重新创建元素时都会重新计算DOM。连接长字符串可能需要一些时间。

2)首先执行JavaScript,然后再渲染页面。浏览器只有一个线程用于执行这些任务。

3)是的,有更好的方法。他们是Create elementsappendinsert。这通常是更多代码,但结果更快。

如果要删除字符串以创建HTML,请使用insertAdjacenHTML代替innerHTML。它更快,因为它不会重新创建元素。如果可能的话,尽可能将HTMLString创建为大部分,并且只将一个字符串放入DOM,这会显着减少重新计算时间。

答案 3 :(得分:1)

1:在javascript字符串中immutable。因此,每次修改字符串时,您实际上都在创建字符串的副本,并将更改附加到该字符串。随着字符串的增长,这可能需要很长时间。

2:在您的javascript执行完毕之前,浏览器不会呈现HTML。你可以处理几个div然后产生控制并使用超时来继续处理。

3:不要使用大量字符串创建HTML。我建议使用模板驱动的方法。您可能想要查看Reactjs或Angular。否则,使用dom方法创建节点并将它们附加到dom中。