有人能向我证明下面给出的建议(以下是复制的链接:http://code.google.com/speed/articles/javascript-dom.html)是更快的,即在修改DOM元素之前删除它们,然后重新插入它们。
我希望看到一些数字来证明这一点。他们研究这个问题很好,但我认为如果不包括具体的“问题”以及解决方案如何在速度方面进行修复(作为文章标题Speeding up JavaScript),那么本文非常薄弱。
该文章...
流外DOM操作
这种模式使我们可以创建多个元素并将它们插入到DOM中触发单个回流。它使用一个称为DocumentFragment的东西。我们在DOM之外创建一个DocumentFragment(因此它不在流中)。然后,我们创建并添加多个元素到其中。最后,我们将DocumentFragment中的所有元素移动到DOM中,但只触发一次回流。 问题
让我们编写一个函数,为元素内的所有锚点更改className属性。我们可以通过简单地迭代每个锚点并更新其href属性来实现这一点。问题是,这可能会导致每个锚点都重新回流。
function updateAllAnchors(element, anchorClass) {
var anchors = element.getElementsByTagName('a');
for (var i = 0, length = anchors.length; i < length; i ++) {
anchors[i].className = anchorClass;
}
}
解决方案
为了解决这个问题,我们可以从DOM中删除元素,更新所有锚点,然后将元素插入回原来的位置。为了帮助实现这一点,我们可以编写一个可重用的函数,它不仅可以从DOM中删除一个元素,还可以返回一个函数,以便将该元素插入回其原始位置。
/**
* 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();
}