9

次のコードは、DOM Mutation Eventを利用して要素DOMNodeInsertedの存在を検出し、それをラッパーにラップします。bodyinnerHTML

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>
        function DOMmanipulation() {
            if (document.body) {
                document.removeEventListener('DOMNodeInserted', DOMmanipulation);
                // DOM manipulation start
                document.body.innerHTML = '<div class="wrapper">' + document.body.innerHTML + '</div>';
                // DOM manipulation end
            }
        }
        document.addEventListener('DOMNodeInserted', DOMmanipulation);
    </script>
</head>
<body>
    <p>Lorem ipsum dolor sit amet.</p>
</body>
</html>

また、ラッピングが成功したにもかかわらず、ノードが見つからなかったことを示すエラーがあります。この質問の回答は、jQueryが読み込まれたときに、いくつかのテストを行うために要素を本体に追加したが、その要素が子ではないようにラッパーにラップされているため、その要素divを削除できなかったためであると説明しましたdivもう体の要素。

上記の実験は、jQueryのテスト要素( )がjQueryによって削除される前にラップされたDOMNodeInsertedため、イベントがjQueryのテストよりも高速であることを示しています。div




これで、次のコードで同じ操作を実行でき、新しく導入されたDOMMutationObserversを使用しています。現時点(2012-07-11)では、Chrome18以降でのみ動作します。

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script>
        var observer = new WebKitMutationObserver(function() {  
            if (document.body) {
                observer.disconnect();
                // DOM manipulation start
                document.body.innerHTML = '<div class="wrapper">' + document.body.innerHTML + '</div>';
                // DOM manipulation end
            }
        });
        observer.observe(document, { subtree: true, childList: true });
    </script>
</head>
<body>
    <p>Lorem ipsum dolor sit amet.</p>
</body>
</html>

このコードはエラーを生成しませんでした。つまり、jQueryはDOM Mutation Observersよりも高速であるため、そのdiv要素をラッパーにラップする前に、テスト要素()を削除することができました。




上記の2つの実験から、実行速度に関しては次のことがわかります。

  • DOMミューテーションイベント>jQueryのテスト
  • jQueryのテスト>DOMMutation Observers

この結果は、DOMミューテーションオブザーバーがDOMミューテーションイベントよりも遅いことを適切に証明できますか?

4

2 に答える 2

26

DOMミューテーションオブザーバーは、DOMミューテーションイベントよりも高速であるようには意図されていません。むしろ、それらはより効率的で安全であることを目的としています。

違いの基本的な要点は、変更があるたびにDOMミューテーションイベントが発生することです。したがって、たとえばこのコードはコールバックループを作成し、最終的にブラウザをクラッシュさせます。

document.addEventListener('DOMNodeInserted', function() {
    var newEl = document.createElement('div');
    document.body.appendChild(newEl);
});

それらがこのように呼び出され、ブラウザ間の中断を強制してスタイルの再計算、リフロー、再ペイントのサイクルを強制するか、さらに悪いことにブラウザにスタイルの再計算、リフロー、再ペイントを強制するため、ブラウザにも大きな影響を与えることがよくあります。折り返し電話。この問題は、DOMにさらに変更を加える他のコードが実行されている可能性があり、コールバックによって引き続き中断されるという事実によってさらに悪化します。

さらに、イベントは通常のDOMイベントと同じように伝播するため、コードで気にしない、または考慮しなかった要素の変更を聞き始めることになります。そのため、DOMミューテーションイベントのメカニズム全体をかなり迅速に管理するのは面倒になる可能性があります。

DOM Mutation Observersは、名前がDOMの変更を監視し、変更の開始から行われたすべての変更のレポートを提供することを示唆しているため、これらの問題に対抗します。これは、たとえばドキュメントがアイドル状態で、さらに変更を加える可能性のある他のすべてのJavaScriptの実行が終了したとき、またはブラウザが再起動する前など、適切な時間にブラウザが通知できるため、はるかに良い状況です。サイクルを再計算/再ペイントするため、直後にサイクルを繰り返すことなく、行った変更を適用できます。

また、変更されたすべての要素をスキャンして、気にしないもののケース処理コードをたくさん書く代わりに、探しているものを見つけることができるため、管理が容易になります。突然変異イベント。さらに重要なのは、一度だけ呼び出すので、それ以上の変更が要素に影響を与えることを心配する必要はありません。つまり、要素は変化している状態ではなく、変化しています。

したがって、あなたの質問に答えると、DOM Mutation Observersは、jQueryがDOMの操作を終了するのを待ってから、jQueryの変更を通知するため、速度が低下します。上記で説明した理由とあなたの例により、より安全で効率的なソリューションであることが証明され(エラーが発生しなくなりました)、jQueryがDOMに何かを追加したのは、すぐに削除されるため、気にしませんでした。オブザーバーを使用すると、追加および削除されるjQuery要素の詳細を示すレポートを受け取ることになります。

ただし、要素をすべての変更と照合することによって実際に何が起こったかを把握する必要があるため、これはまだ少し厄介です。現実には、あなたに関する限り、何も起こらなかった(同じ要素が追加および削除された)ので、DOMの構造は実際には何も変更されていません。これを支援するために、MutationSummaryと呼ばれる小さなライブラリがあります。

http://code.google.com/p/mutation-summary/

これは、変更の正味の効果を計算し、それらの変更を渡すコールバックのみを呼び出します。したがって、あなたの場合、変更の正味の効果はゼロだったので、コールバックはまったく呼び出されなかったでしょう。

たとえば、次の場合、変更は1つだけです。ボディスタイルは左に変更されました:1000px。1000刻みで変えたのに。変更の正味の効果は、初期値と最終値の差のみです。

function moveBody() {
    for (var i = 0; i < 1000; i++) document.body.style.left = i + 'px';
}
moveBody();
于 2012-07-30T22:26:22.967 に答える
7

簡単な答えは、ミューテーションオブザーバーは非同期であるということです。これらは、エンジンがそのように感じたとき、変更が行われた後、場合によっては非常に多くの変更が行われた後に送信されます。これは、DOMミューテーションイベントリスナーから通知されてからかなり時間がかかる場合がありますが、その間、エンジンは、DOMが変更されるたびにイベントを作成してバブルすることなく、自由に作業を実行できます。

于 2012-10-09T18:52:07.867 に答える