当查看父节点的子节点时,数据结构似乎是一个像对象的数组。
代替遍历每个childNode并删除它-是否可以仅删除类似数组的对象?
我在这里考虑表演,并希望避免遍历孩子并一一删除。
就我而言,我正在父级Ul上创建子级Li元素:
_createLi(address) {
const parentUl = document.querySelector("ul#parent");
const li = document.createElement("li");
li.appendChild(document.createTextNode(address));
parentUl.appendChild(li);
}
我可以这样删除它们:
_removeLi(node) {
while (!node.lastChild) node.removeChild(!node.lastChild);
}
这有效,但是遍历每个节点。 您如何通过删除包含子节点的数组之类的对象来删除所有子节点,并且在O(1)中是否可能?
答案 0 :(得分:2)
我真的怀疑即使在使用node.innerHTML = ''
的情况下也可以在O(1)中删除子级,因为基础实现很可能是O(N)操作。
您应该考虑提高性能的是,尽量减少DOM回流的次数。
const list = document.querySelector('ul');
const listClone = list.cloneNode(false);
list.parentNode.replaceChild(listClone, list);
<ul>
<li>First</li>
<li>Last</li>
</ul>
withElOutOfFlow(document.querySelector('ul'), el => {
while(el.lastChild) el.removeChild(el.lastChild);
});
function withElOutOfFlow(el, callback) {
const parent = el.parentNode;
if (!parent) {
callback(e);
return;
}
const nextSibling = el.nextSibling;
parent.removeChild(el);
callback(el);
if (nextSibling) parent.insertBefore(el, nextSibling);
else parent.appendChild(el);
}
<ul>
<li>First</li>
<li>Last</li>
<ul>
答案 1 :(得分:2)
.cloneNode()
and .replaceChild()
5% faster than ALL examples
(包括接受的答案)
以下示例来自 Range API :
const rng = document.createRange(); rng.selectNodeContents(document.querySelector('ul')); rng.deleteContents();
范围界面处理由节点和文本组成的文档片段。尽管它显示的时间很慢,但it's actually fast和100% compatible with all browsers。
范围方法
.replaceWith()
和.createElement()
15% slower than All examples
此组合比大多数示例都快,且冗长(除了 Range 演示最快)。
document.querySelector('ul').replaceWith(document.createElement('ul'));
这是2个DOM交互:查找列表并将其替换为空列表。请参阅演示1。If you want to support IE11 (ATM 2.26% global share),然后不要使用它。
const rng = document.createRange();
rng.selectNodeContents(document.querySelector('ul'));
rng.deleteContents();
ul {
min-height: 30px;
min-width: 30px;
outline: 1px dashed red;
}
<ul>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
</ul>
.replaceWith()
和.createElement()
document.querySelector('ul').replaceWith(document.createElement('ul'));
ul {
min-height: 30px;
min-width: 30px;
outline: 1px dashed red;
}
<ul>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
</ul>
.insertAdjacentHTML()
和.createDocumentFragment()
比所有示例慢50%
优化任何DOM操作的最佳方法是不要使用它们。将DOM访问限制到最低限度–这非常耗时。每次JS引擎寻找元素时,它将遍历DOM树,每次添加或删除标签时,都必须重新计算DOM中已经存在的节点(元素,文本等)的位置和尺寸,因此即使如果所涉及的节点数很少,那么对于浏览器来说,这可能会花费很多时间。这称为重排,涉及CSS样式的类似问题称为重绘。
<li>
中的所有<ul>
:
引用
<ul>
-1查找
<ul>
的引用父项附加一个空的<ul>
-1个查询,1个添加项创建一个
documentFragment
并将原始<ul>
附加到其中-删除1次
.insertAdjacentHTML()
无损地将htmlString
渲染为HTML和it's highly optimized。
.createDocumentFragment()
never touches the DOM,附加的内容不再与DOM接触。
.insertAdjacentHTML
和.createDocumentFragment()
// Reference the <ul>
const list = document.querySelector('ul');
// Reference parent of <ul> append an empty <ul>
list.parentElement.insertAdjacentHTML('beforeend', `<ul></ul>`);
// Create a document fragment and append original <ul> to it
document.createDocumentFragment().appendChild(list);
ul {
min-height: 30px;
min-width: 30px;
outline: 1px dashed red;
}
<ul>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
<li>ITEM</li>
</ul>