web-dev-qa-db-ja.com

DOMの変更を検出/監視する最も効率的な方法は?

DOMの変更を検出するための効率的なメカニズムが必要です。クロスブラウザが望ましいですが、notクロスブラウザである効率的な手段があれば、フェイルセーフクロスブラウザメソッドでこれらを実装できます。

特に、ページ上のテキストに影響する変更を検出する必要があるため、新しい要素、削除された要素、変更された要素、または内部テキスト(innerHTML)への変更が必要になります。

行われている変更を制御することはできません(サードパーティのjavascriptのインクルードなどが原因である可能性があります)。この角度からアプローチすることはできません。変更を「監視」する必要があります。

現在、私は定期的にbody.innerHTML.lengthをチェックする "quick'n'dirty"メソッドを実装しています。もちろん、これは同じ長さが返される変更を検出しませんが、この場合は「十分」です-この問題が発生する可能性は非常に少なく、このプロジェクトでは、変更の検出に失敗しても結果は発生しません。失われたデータ。

body.innerHTML.lengthの問題は、高価だということです。 fastブラウザーでは1から5ミリ秒かかることがあり、これにより物事が非常に行き詰まる可能性があります-私はまた、大量のiframeを処理していますが、すべてが加算されます。 innerHTMLテキストはブラウザーによって静的に保存されず、読み込まれるたびにDOMから計算する必要があるため、これを行うことのコストはかなり高いと確信しています。

私が探している答えのタイプは、「正確な」(たとえばイベント)から「十分な」ものまであります。innerHTML.lengthメソッドのように「quick'n'dirty」のようなものですが、より高速に実行されます。

編集:また、修正された正確な要素を検出するのは「いい」ことですが、絶対に必要というわけではありません-any変更があったという事実は十分ですこれが人々の反応を広げることを願っています。 Mutation Eventsを調査しますが、IEサポートのフォールバックがまだ必要です。そのため、奇抜で創造的な正方形外のアイデアは大歓迎です。

46
Graza

http://www.quirksmode.org/js/events/DOMtree.html

jQueryは、セレクターに対応する既存および将来の要素にイベントをアタッチする方法をサポートするようになりました。 http://docs.jquery.com/Events/live#typefn

別の興味深い発見- http://james.padolsey.com/javascript/monitoring-dom-properties/

10
jagamot

これを最新の状態にするために、DOM4標準はMutation Eventsを廃止し、Mutation Observersに置き換えます: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

33
zeveck

突然変異イベント は、あなたが探しているもののW3勧告です。

それらがすべての場所でサポートされているかどうかはわかりません。

8

DOMNodeInsertedおよびDOMNodeRemovedイベントを使用してみてください。 Quirksmodeによれば、IEの顕著な例外を除いて、ほとんどのブラウザーで動作します...

http://www.quirksmode.org/dom/events/index.html

1
Chibu

私は最近、まさにそれを行うプラグインを作成しました- jquery.initialize

_.each_関数と同じ方法で使用します

_$(".some-element").initialize( function(){
    $(this).css("color", "blue"); 
});
_

_.each_との違いは、セレクター(この場合は_.some-element_)を使用し、将来このセレクターで新しい要素を待機することです。そのような要素が追加されると、初期化されます。

この場合、initialize関数は要素の色を青に変更するだけです。そのため、次のような新しい要素を追加する場合(ajaxやF12インスペクターなどを使用する場合でも):

_$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
_

プラグインはすぐに初期化します。また、プラグインは、1つの要素が一度だけ初期化されるようにします。したがって、要素を追加してから、.deatch()をbodyから追加してから再度追加すると、再び初期化されません。

_$("<div/>").addClass('some-element').appendTo("body").detach()
    .appendTo(".some-container");
//initialized only once
_

プラグインはMutationObserverに基づいています-IE9および10で動作し、依存関係は readmeページ で詳しく説明されています。

1
pie6k

jQuery Mutateもこれを行います。デフォルトではheight, width, scrollHeight etc ...ただし、テキストが変更されたかどうかを確認するなどの新しいイベントを追加するために、少しの追加コードで拡張することもできます。

http://www.jqui.net/jquery-projects/jquery-mutate-official/

それが役に立てば幸い

0
Val