【问题标题】:Why appendChild triggers Recalculate Style whereas setting innerHTML don't on Chrome?为什么 appendChild 触发重新计算样式,而在 Chrome 上设置 innerHTML 不?
【发布时间】:2012-10-31 21:33:36
【问题描述】:

使用 Chrome 开发者工具中的时间轴,我用这小段代码通过 innerHTMLappendChild 方法记录事件:

<!DOCTYPE html>

<html>
<head>
  <script>
    function testInnerHTML(){
      var wrap = document.getElementById('wrapper');
      wrap.innerHTML = "test";
    }
    function testAppendChild(){
      var wrap = document.getElementById('wrapper');
      wrap.appendChild(document.createTextNode("test"));
    }
  </script>
</head>

<body>
  <input type="button" value="innerHTML" onClick="testInnerHTML();"/>
  <input type="button" value="appendChild" onClick="testAppendChild();"/>
  <div id="wrapper"></div>
</body>
</html>

我可以看到:

  • innerHTML 触发 layout 事件
  • appendChild 触发 layout 事件和 recalculate style 事件

在这个示例中,每个事件几乎不需要处理任何事情,并且似乎或多或少是并行发生的,但是如果您使用大型 html 表执行此操作,您会发现重新计算样式可能需要几秒钟,并且布局将在此之后发生。所以如果我们能避免它,那就更好了!

我正在考虑使用带有文档片段的 appendChild 来避免 innerHTML 涉及的解析。但是以这种方式节省的时间被重新计算样式丢失了......

我使用的是 Chrome 版本 23.0.1271.64 m

你知道为什么会这样吗? 我是否应该向我附加的节点添加一些东西以帮助浏览器不触发重新计算样式事件?

PS:如果对双重解析事件有疑问,可以参考Why does a click setting innerHTML trigger two parsing events on Chrome?

【问题讨论】:

  • "并且似乎或多或少平行发生" 事件标记的宽度最小,这就是它们看起来像重叠的原因。所有这些事件都发生在一个线程中。

标签: javascript html google-chrome google-chrome-devtools


【解决方案1】:

在WebKit中,HTMLElement::setInnerHTML()内部使用replaceChildrenWithFragment(),有以下特殊情况:

if (hasOneTextChild(containerNode.get()) && hasOneTextChild(fragment.get())) {
    toText(containerNode->firstChild())->setData(toText(fragment->firstChild())->data(), ec);
    return;
}

ContainerNode::appendChild() 不同,后者只是将节点迭代地插入容器并分派相应的事件(例如 DOMNodeInserted。)

我同意这可能需要一些优化。

【讨论】:

  • 确实,它可以解释给出的简单示例。但是您可以尝试使用更复杂的 HTML 字符串,但仍然没有触发重新计算样式:wrap.innerHTML = &lt;span&gt;test&lt;/span&gt;something more&lt;table&gt;&lt;tr&gt;&lt;td&gt;complicate&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
  • 好吧,您可以尝试分别创建DocumentFragmentappendChildwrap,看看在这种情况下会发生什么。
猜你喜欢
  • 2010-12-23
  • 2012-10-31
  • 2016-04-14
  • 2014-12-22
  • 2021-08-05
  • 1970-01-01
  • 2012-01-02
  • 2018-04-07
  • 2021-06-09
相关资源
最近更新 更多