快速与容器内的大量元素进行交互(DOM,javascript) [英] fast interacting with large number of elements inside a container (DOM, javascript)

查看:77
本文介绍了快速与容器内的大量元素进行交互(DOM,javascript)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有一个容器div内有大量的div(4000-5000)[每个都包含跨度,锚点,图像等],基本上我将它们的显示设置为none或根据条件进行阻塞。这需要一些时间。



在我搜索更快的东西时,我遇到了这个页面https://developers.google.com/speed/articles/javascript-dom ,解决方案是从DOM中删除容器div,并通过getElementsByTagName迭代包含的元素。

  / ** 
*移除一个元素并提供一个将其插入原始位置的函数
* @ param元素{元素}要临时移除的元素
* @return {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();
}

问题是我无法使用提供的解决方案,因为我需要访问子项元素由他们的ID和我不能这样做,因为元素从DOM中删除。有没有办法实现这一目标?



我也尝试删除容器div并将其附加到文档片段,但仍然无法访问它们的5000个元素ID,当他们在文档片段中



最后,我也试过这个:

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

//遍历5000个子div并更改它们的类名

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

因为我希望它不会触发每次迭代的回流,但是这似乎没有以提供所需时间的改进。



有人对此有任何想法吗?

解决方案

显示无/块很贵。从我在改善网络交易平台性能的日子里,我可以推荐一种技术,尤其是对于旧版浏览器,我会推荐一种技术,即使用相对位置,并使用负左值将其从屏幕上拉下。当然,根据您的实施情况,您可能也希望将高度设置为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.

这篇关于快速与容器内的大量元素进行交互(DOM,javascript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆