【发布时间】:2010-12-23 02:09:45
【问题描述】:
有人可以向我证明here(复制如下)关于在更改它们然后重新插入它们之前删除 dom 元素的建议更快。
通过证明,我希望看到一些数字。他们研究这个很好,但我认为这篇文章非常薄弱,没有详细说明“问题”到底是什么以及解决方案如何解决速度方面的问题(如文章标题加速 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();
}
【问题讨论】: