检查父节点是否相等,不考虑子节点

3
我希望您能快速查看两个元素是否相等,无论它们有什么子元素。isEqualNode不起作用,因为它也比较了元素的子节点。
所以,在这个例子中,我想编写一个函数,如果给出两个<div class="foo" style="background-color: green;">元素作为参数,即使它们具有不同的子元素,也会返回true。
<div class="foo" style="background-color: green;">
  <h3>bar</h3>
  Hello
</div>

<div class="foo" style="background-color: green;">
  <div class="goat" />
</div>

<script>
  function checkIfParentNodesAreEqual(el1, el2) { /* magic */}

  var els = document.getElementsByClassName('foo');
  checkIfParentNodesAreEqual(els[0], els[1]) // I want this to return true
</script>

我在想,从性能角度来看,如何判断这两个元素是否相等?

我知道我们可以对这两个节点进行浅克隆并比较克隆体,或者删除所有子节点,比较父节点,然后重新附加子节点,但我想知道是否有更快的方法。


定义 两个父母相等 - madalinivascu
我已经编辑了问题,希望现在更加清晰明了。 - Tyson Hauke
不同的内联样式会使它不相等吗? - JohanP
是的 @JohanP,我基本上正在尝试找到一个不比较子节点的isEqualNode函数。 - Tyson Hauke
这是一个比较难解决的问题。即使这两个节点没有子节点,isEqualNode也会返回false,例如:<div class="foo" style="background-color: green;color:red;"><div class="foo" style="color:red;background-color: green;"> - JohanP
@TysonHauke 为什么不直接比较这些类,你需要比较它们是否具有相同的样式? - madalinivascu
3个回答

2
您可以尝试克隆节点,删除它们的子节点,然后进行比较。 由于我们正在进行克隆操作,因此无需重新附加子节点。
var eles = document.getElementsByClassName('foo');
var parent1 = eles[0].cloneNode(true);
var parent2 = eles[1].cloneNode(true);

parent1.innerHTML = '';
parent2.innerHTML = '';

function checkIfParentNodesAreEqual(parent1, parent2) { /* magic */}

希望这能有所帮助。


2

为了比较节点,您需要进行浅复制,操作如下:

function compareNodes (nodes, shallow) {
  if (shallow) nodes = nodes.map((node) => node.cloneNode(false))
  return nodes.every((node, index, nodes) => {
    let nextIndex = index + 1
    return nodes[nextIndex] ? node.isEqualNode(nodes[nextIndex]) : true
  })
}

compareNodes(Array.from(document.getElementsByClassName('foo')), true)

但正如您所说,您正在寻找一种可能更有效的替代方案。我不认为上述实现非常低效,但您必须针对您的应用程序自行测试并查看其性能。我能想到的一种替代方案是使用虚拟DOM并利用其差异算法,但它们也有缺点 - 如Auth0的这篇博客文章中所概述的。您将不得不深入了解它们以找出要使用的实现。尽管我相信您会很好地完成上述实现。
更新:我在上述实现上进行了一些测试,比较了总共1,000个节点,包括对每个节点进行浅复制,平均需要3毫秒。

太棒了!非常感谢提供链接,我已经快速浏览了一下,看起来使用虚拟DOM可能是正确的方法,但是正如你所说,我需要做更多的调查。 - Tyson Hauke
很高兴我能帮到你! :) 我对这个实现的性能进行了一些测试,并将其作为更新添加到了我的答案中。但请注意,里程可能因系统和应用程序而异。 - Svenskunganka

0
在某个时候,函数isSameNode()被定义了,但现在更推荐使用===运算符(三个等号)来验证两个元素是否确实是同一个元素:
function checkIfParentNodesAreEqual(el1, el2) 
{ 
  /* magic */
  return( el1.parentElement === el2.parentElement );
}

如果您更喜欢使用parentNode属性而不是parentElement,请查看HTML DOM parentElement Property

有关比较的更多详细信息,请查看HTML DOM isSameNode() Method


采用这种方法,当其他节点为<div class="foo" style="background-color: green;">时,<div class="foo" style="background-color: green;color:red">将为真。不确定是否被视为“相等”。 - JohanP
@JohanP,也许你在想isEqualNode(),它比较节点的特征(类型、属性等)以确定它们是否相等(不一定相同)。 - Octavio Galindo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接