且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

快速与容器内的大量元素进行交互(DOM,javascript)

更新时间:2023-08-26 18:35:16

显示无/块很贵。从我在改善网络交易平台性能的日子里,我可以推荐一种技术,尤其是对于旧版浏览器,我会推荐一种技术,即使用相对位置,并使用负左值将其从屏幕上拉下。当然,根据您的实施情况,您可能也希望将高度设置为0px,或者查看绝对位置的可能性。核心概念仍然是,你只是简单地将元素从屏幕上撤下。好消息是隐藏的元素仍然在DOM中,您可以访问它们。

  div {
position:relative;
left:0px;
}
div.hide {
left:-4096px;
height:0px;

$ / code>

检查这两个小提琴,它们创建10K行并切换(隐藏/显示)奇数行:



使用Display none / block的FIDDLE

a>

使用位置和高度的FIDDLE p>

Chrome可以轻松处理100K这些行,并且很难看到显着的性能提升,而对于Firefox,我不得不将行数减少到10K,性能提高很多更明显。


So I have a large number of divs (4000-5000) [each contains spans, anchors, images etc.] inside a container div and basically I am setting their display to none or block based on a condition. This does take some time.

In my search for something faster I came across this page https://developers.google.com/speed/articles/javascript-dom and the solution there is to remove the container div from the DOM and iterate the contained elements by getElementsByTagName.

/**
 * Remove an element and provide a function that inserts it into its original position
 * @param element {Element} The element to be temporarily removed
 * @return {Function} A function that inserts the element into its original position
 **/
function removeToInsertLater(element) {
  var parentNode = element.parentNode;
  var nextSibling = element.nextSibling;
  parentNode.removeChild(element);
  return function() {
    if (nextSibling) {
      parentNode.insertBefore(element, nextSibling);
    } else {
      parentNode.appendChild(element);
    }
  };
}


function updateAllAnchors(element, anchorClass) {
  var insertFunction = removeToInsertLater(element);
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
  insertFunction();
}

The problem is I cannot use the solution provided because I need to access the children elements by their IDs and I can't do that, since the elements are removed from the DOM. Is there any way to achieve this?

I also tried to remove the container div and append it to a documentfragment, but still I can't access the 5000 elements by their ID when they are in the documentfragment

Finally, I also tried this:

document.getElementById("CONTAINERDIV").style.display = "none";

//iterate through the 5000 children divs and change their classname

document.getElementById("CONTAINERDIV").style.display = "block";

because I was hoping that it would not trigger a reflow for each iteration, but this didn't seem to provide an improvement in the time required.

Does anyone have any thoughts on this?

Display none/block is expensive. From my days of improving performance on trading web platforms, one technique I can recommend that'll shine especially with older browsers is to use position relative and yank it off the screen using a negative left value. Of course depending on your implementation, you might want to set the height to 0px as well or look into possibilities with position absolute. The core concept still remains that you are simply yanking the element off the screen. Good news is that the elements hidden are still in the DOM and you can access them.

div {
  position: relative;
  left: 0px;
}
div.hide {
  left: -4096px;
  height: 0px;
} 

Check out these two fiddles, they create 10K rows and toggle(hide/show) the odd rows:

FIDDLE using Display none/block

FIDDLE using Position and Height

Chrome handles 100K of these rows in a snap and it's difficult to see a significant performance improvement, whereas for Firefox I had to reduce the row count to 10K and the performance gain is much more apparent.