如何复制节点列表?
Posted
技术标签:
【中文标题】如何复制节点列表?【英文标题】:How to copy a nodelist? 【发布时间】:2019-10-16 09:56:59 【问题描述】:我正在尝试为大约 1000 行的大表设置搜索功能。这样做的问题是渲染会大量消耗性能。这是因为我正在遍历表中的所有行并将不包含搜索查询的行的样式设置为“无”。
由于某种原因,每次我进行更改时,浏览器都会重新呈现所有元素。我通过 document.quesrtySelectorAll('tbody tr') 将表数据作为节点列表获取。我的解决方案是将其复制到一个新对象,对新对象进行搜索和样式更改,然后将其复制回来,导致浏览器只需重新渲染一次表格。
let items = document.querySelectorAll('tbody tr');
let itemsArr = [...items];
for (let ele of itemsArr)
. . .
if (!lower_case_table_value.match(lower_case_search_value))
ele.style.display = 'none';
else
ele.style.display = 'table-row';
let list = document.querySelector('tbody');
for (let i = 0; i < items.length; i++)
list.appendChild(itemsArr[i]);
不过,无论我做什么,我对新对象所做的任何更改都会对旧对象进行更改。我删除了第二个 for 循环,它的行为就像什么都没发生一样。就好像它不是一个副本,而是一个指针。
有人知道谁将节点列表复制到一个新对象并确保它们是独立的而不是彼此的指针吗?
【问题讨论】:
嗨,也许可以给我们一个关于你的桌子的小sn-p,以及你是如何尝试复制文件的。 @Andreas 谢谢我刚刚进行了编辑。 在服务器端形成表格所需的特征不是更容易吗?如果tr
包含没有数据的td
,那么只需像style="display: none"
一样附加smth
您错过了let itemsArr = [items];
中的...
吗?否则这根本行不通(因为ele === items
)。
在for...of...
循环中,您正在更改元素的display
属性。第二个循环和.appendChild()
不是必需的(只会为浏览器添加更多不必要的工作(重排))。这需要进行一些测试,但我猜想克隆 DOM 节点、更改克隆、删除旧节点和添加克隆会比更改样式花费更多时间。
【参考方案1】:
今天偶然发现同样的问题,发现可以使用“node.cloneNode”方法复制一个DOM节点元素,例如:
let p = document.getElementById("para1")
let p_prime = p.cloneNode(true)
我从 MDN 文档中获取了 sn-p,您可以在此处找到: https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
很可能您已经找到了解决方案,但无论如何,我将这里留作记录。
【讨论】:
【参考方案2】:let items = document.querySelectorAll('tbody tr');
let itemsArr = [...items];
这里的 items 是一个 nodeList 所以 itemsArray 也存储了一个 nodeList 现在如果你尝试迭代 itemsArray 里面只有一件事,就是你放在那里的 nodeList 如果您将散布项目添加到 itemsArray 中,您将存储元素而不是整个 odeList
【讨论】:
我正在这样做,但同样,它并没有将其视为一个单独的对象。如果我对 itemsArr 进行更改,它也会对 items 进行更改。【参考方案3】:如果你想获得一个新的 Array 而不是 chilNode
使用Array.from(nodeToCopy)
这将返回一个新数组而不是子节点
【讨论】:
这不起作用。它仍然将其视为指向原始对象的指针。nodeToCopy
(一个 DOM 节点)和Array.from()
(从可迭代对象创建数组)如何协同工作? o.O
如果你有一个 NodeList 你想变成一个数组
1. TO 已经这样做了(使用[...items]
),2. 你在谈论子节点,nodeToCopy
仍然是单数,在这种情况下没有多大意义
我现在明白了以上是关于如何复制节点列表?的主要内容,如果未能解决你的问题,请参考以下文章