3

Chrome デベロッパー ツールのタイムラインを使用して、次の小さなコードを使用して、innerHTMLメソッドとappendChildメソッドを通じてイベントを記録しました。

<!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はレイアウトイベント をトリガーしますinnertHTML トリガー レイアウト イベント
  • appendChildは、レイアウトイベントとスタイルの再計算イベント をトリガーします。appendChild はレイアウトをトリガーし、スタイル イベントを再計算します

このサンプルでは、​​各イベントの処理にほとんど時間がかからず、多かれ少なかれ並行して発生しているように見えますが、たとえば大きな html テーブルでこれを行うと、スタイルの再計算に数秒かかる場合があり、そのレイアウトが行われることがわかります。その後。ですから、それを避けることができれば、それは良いことです!

innerHTML による解析を避けるために、ドキュメント フラグメントで appendChild を使用することを考えていました。しかし、そのように節約された時間は、再計算スタイルによって失われます...

Chrome バージョン 23.0.1271.64 m を使用しています

なぜこれが起こるのか分かりますか?ブラウザがスタイルの再計算イベントをトリガーしないようにするために、追加するノードに何かを追加する必要がありますか?

PS:二重解析イベントについて疑問がある場合は、「Why does a click setting innerHTML triggers two parsing events on Chrome? 」を参照してください。

4

1 に答える 1

2

WebKitでは、HTMLElement::setInnerHTML()内部的にを使用しますreplaceChildrenWithFragment()。これには、次の特殊なケースがあります。

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

とは対照的にContainerNode::appendChild()、ノードをコンテナに繰り返し挿入し、それぞれのイベントをディスパッチします(例DOMNodeInserted)。

私はこれがいくつかの最適化を使用するかもしれないことに同意します。

于 2012-11-12T14:05:18.360 に答える