IE11 DOM 规范化不适用于 table 行

IE11 DOM normalize doesn't work with table row

我想标准化 table 行。这就像一个魅力,除了在 IE 中(用 IE 11 测试)。

我创建了一个演示片段来演示该问题:

$(function() {
  $("table tbody tr span").each(function() {
    var $this = $(this);
    var $parent = $this.parent();
    $this.replaceWith($this.html());
    $parent[0].normalize();
  });
});
<link href="https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table table-striped table-hover">
  <thead>
    <tr>
      <th>President</th>
      <th>Birthplace</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><span>Zach</span>ary Taylor</td>
      <td>Barboursville, Virginia</td>
    </tr>
  </tbody>
</table>

这会用其内容替换 <span> 元素。在这一步之后,节点将如下所示:

然后调用normalize()合并拆分后的文本节点。但是,在 IE11 中,文本节点仍然是拆分的。

我看不出有任何问题。这个问题的原因是什么,解决方案是什么?


原来是IE11的bug,所以填了一个bug report!

IE-11 似乎无法规范化文档中已有的元素如果您的开发人员工具栏已打开

This is also relevant for IE9 & 10 (emulated by using meta http-equiv="X-UA-Compatible" tag)

当您只创建新节点而不将它们附加到文档时 - 一切正常(对于这两种情况 - 开发人员工具栏打开和关闭):

d = document.createElement('div');
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - Should be 2')
d.normalize();
console.log(d.childNodes.length + ' - Should be 1')

但是,如果您使用的节点已经是文档的一部分,normalize 功能将不起作用如果您的开发人员工具栏已打开

d = document.getElementsByTagName('div')[0];
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - should be 2 on every browser')
d.normalize();
console.log(d.childNodes.length + ' - should be 1, however it\'s 2 on IE')
<div></div>

如果你真的想要,你可以做的是从文档中提取节点并在规范化后添加它们:

d = document.getElementsByTagName('div')[0];
d.appendChild(document.createTextNode('text 1'));
d.appendChild(document.createTextNode('text 2'));
console.log(d.childNodes.length + ' - should be 2 on every browser')

dNew = d.cloneNode(true)
dNew.normalize()
d.parentElement.replaceChild(dNew, d)

d = document.getElementsByTagName('div')[0];
console.log(d.childNodes.length + ' - should be 1 on every browser')
<div></div>

更新 - 28/8
@dude 发表评论后更新了答案。在这里调查原因花了一些时间,但我认为现在我已经涵盖了所有内容。

Note that for IE8 (forced by using <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8"> in IE-11) the normalize() function works for both elements that are in the DOM tree and elements that are not, even with the developers toolbar was open.

我对 DOM.normalize() 不太熟悉,但如果您已经在使用 jQuery,那么操作元素的内容非常容易。我最喜欢的删除不必要的嵌套标签的方法是像这样使用 $.text() :

$("table tbody tr span").each(function() {
  var $parent = $(this).parent();
  $parent.html($parent.text());
});

如果您的用例确实像您发布的一样简单,则此方法有效。对于更复杂的用例,还有许多其他方法可以执行此类操作。