如何比较两个HTML元素

rjee0c15  于 2022-12-02  发布在  其他
关注(0)|答案(4)|浏览(169)

我们如何比较两个HTML元素是否相同?
我试过了,但没成功

<div class="a"> Hi this is sachin tendulkar </div>
<div class="a"> Hi this is sachin tendulkar </div>

然后单击按钮,调用函数check()

var divs = $(".a");
alert(divs.length);    // Shows 2 here which is correct
if (divs.get(0) == divs.get(1)) alert("Same");

但是这是行不通的。在两个div中所有的东西都是一样的。除此之外,我们如何比较两个HTML元素是否完全相同呢?包括它们的innerHTML,className,Id和它们的属性。
这可行吗?
实际上,我有两个HTML文档,我想从它们中删除相同的内容,这样两个元素就可以有相同的id。
PS:在Crowder的宝贵意见之后更新。如果我们比较两个元素作为字符串,我们不会得到匹配,因为它们的属性顺序可能会变化。所以唯一的选择是迭代通过每个子属性和匹配。我仍然必须找出完全工作的实现策略。

mw3dktmi

mw3dktmi1#

您可以用途:

element1.isEqualNode(element2);

在您的具体示例中:

var divs = $(".a");
if ( divs.get(0).isEqualNode(divs.get(1)) ) alert("Same");

DOMLevel3核心规范包含所有的细节。本质上,如果两个节点具有匹配的属性、后代和后代的属性,则返回true。
有一个类似的.isSameNode(),只有当两个元素是相同的节点时才返回true,在你的例子中,它们不是相同的节点,但它们是相等的节点。

li9yvcax

li9yvcax2#

更新

参见Keen's answerccproj's answer to a closely-related question,这里有isEqualNode,但是它将classstyle属性作为文本进行比较,所以相同的类集合或相同的样式属性集合在不同的顺序下会使它认为节点是不等价的。ccprog's answer处理这个问题。

原始答案

  • (下面是一个完整的、基本上未经测试的、当然也没有经过重构的现成解决方案。但首先,我们要介绍它的一些细节。)*

比较它们的innerHTML很容易:

if (divs[0].innerHTML === divs[1].innerHTML)
// or if you prefer using jQuery
if (divs.html() === $(divs[1]).html()) // The first one will just be the HTML from div 0

......尽管您必须自问,根据您的标准,这两个元素是否等价:

<div><span class="foo" data-x="bar">x</span></div>
<div><span data-x="bar" class="foo">x</span></div>

......因为他们的innerHTML将是 * 不同的 *(至少在Chrome上是这样,我怀疑在大多数浏览器上是这样)。
然后需要比较它们的所有属性。据我所知,jQuery没有给予枚举属性的方法,但DOM提供了:

function getAttributeNames(node) {
  var index, rv, attrs;

  rv = [];
  attrs = node.attributes;
  for (index = 0; index < attrs.length; ++index) {
    rv.push(attrs[index].nodeName);
  }
  rv.sort();
  return rv;
}

然后

var names = [getAttributeNames(div[0]), getAttributeNames(div[1])];
if (names[0].length === names[1].length) {
    // Same number, loop through and compare names and values
    ...
}

请注意,通过对上面的数组进行排序,我假设它们的属性顺序在“等价”的定义中并不重要。我希望是这样,因为它似乎没有被保留,因为当我运行this test时,从不同的浏览器得到不同的结果。既然如此,我们必须回到innerHTML问题上。因为如果元素本身的属性顺序并不重要,那么后代元素的属性顺序也应该不重要,如果是这种情况,那么就需要一个递归函数,根据等价元素的定义来检查后代元素,且根本不使用innerHTML
然后是this subsequent question提出的问题:如果元素具有不同但等效的style属性,该怎么办?例如:

<div id="a" style="color: red; font-size: 28px">TEST A</div>
<div id="b" style="font-size: 28px; color: red">TEST B</div>

My answer there通过遍历元素的style对象的内容来处理它,如下所示:

const astyle = div[0].style;
const bstyle = div[1].style;
const rexDigitsOnly = /^\d+$/;
for (const key of Object.keys(astyle)) {
    if (!rexDigitsOnly.test(key) && astyle[key] !== bstyle[key]) {
        // Not equivalent, stop
    }
}
// Equivalent

可悲的是,正如我在回答中所说:
请注意,如果出现 (其中一个为color: red,另一个为color: #ff0000,上述操作将失败,至少在某些浏览器上是这样,因为当样式属性使用字符串值时,通常您会获得提供的值,而不是标准化的值。您可以使用getComputedStyle来获得计算的(ish)值,但这样我们就会遇到CSS适用性方面的问题:标记完全相同的两个元素可能具有不同于getComputedStyle的值,这是因为它们在DOM中的位置以及作为结果应用于它们的CSS。并且getComputedStyle不能在不在文档中的节点上工作,所以您不能仅仅克隆节点来解决这个问题。
但是你应该能够把上面的东西放在一起,根据你的标准来比较两个元素。
更多探索:

这个问题让我很感兴趣,所以我在这个问题上花了一段时间,得出了以下结论。它大部分未经测试,可能需要一些重构等,但它应该会让你走上大部分的路。我再次假设属性的顺序并不重要。以下假设即使是文本中最轻微的差异 * 都 * 重要。

function getAttributeNames(node) {
  var index, rv, attrs;

  rv = [];
  attrs = node.attributes;
  for (index = 0; index < attrs.length; ++index) {
    rv.push(attrs[index].nodeName);
  }
  rv.sort();
  return rv;
}

function equivElms(elm1, elm2) {
  var attrs1, attrs2, name, node1, node2;

  // Compare attributes without order sensitivity
  attrs1 = getAttributeNames(elm1);
  attrs2 = getAttributeNames(elm2);
  if (attrs1.join(",") !== attrs2.join(",")) {
    display("Found nodes with different sets of attributes; not equiv");
    return false;
  }

  // ...and values
  // unless you want to compare DOM0 event handlers
  // (onclick="...")
  for (index = 0; index < attrs1.length; ++index) {
    name = attrs1[index];
    if (elm1.getAttribute(name) !== elm2.getAttribute(name)) {
      display("Found nodes with mis-matched values for attribute '" + name + "'; not equiv");
      return false;
    }
  }

  // Walk the children
  for (node1 = elm1.firstChild, node2 = elm2.firstChild;
       node1 && node2;
       node1 = node1.nextSibling, node2 = node2.nextSibling) {
     if (node1.nodeType !== node2.nodeType) {
       display("Found nodes of different types; not equiv");
       return false;
     }
     if (node1.nodeType === 1) { // Element
       if (!equivElms(node1, node2)) {
         return false;
       }
     }
     else if (node1.nodeValue !== node2.nodeValue) {
       display("Found nodes with mis-matched nodeValues; not equiv");
       return false;
     }
  }
  if (node1 || node2) {
    // One of the elements had more nodes than the other
    display("Found more children of one element than the other; not equivalent");
    return false;
  }

  // Seem the same
  return true;
}

示例:

nimxete2

nimxete23#

为什么不简单一点呢?

<div id="div1"><div class="a"> Hi this is sachin tendulkar </div></div>
<div id="div2"><div class="a"> Hi this is sachin tendulkar </div></div>

if($('#div1').html() == $('#div2').html())
    alert('div1 & div2 are the same');        
else
    alert('div1 & div2 are different');

http://jsfiddle.net/5Zwy8/1/

v440hwme

v440hwme4#

这是怎么编码的?

var d1 = document.createElement("div");
d1.appendChild(divs.get(0));
var d2 = document.createElement("div");
d2.appendChild(divs.get(1));
if (d1.innerHTML == d2.innerHTML) ?

相关问题