web-dev-qa-db-ja.com

JavaScript / jQuery DOM変更リスナーはありますか?

基本的に私はDIVの内容が変わったときにスクリプトを実行させたいのです。スクリプトは独立しているため(Chrome拡張機能のコンテンツスクリプトとWebページスクリプト)、DOMの状態の変化を簡単に観察する方法が必要です。私は投票を設定することができましたが、それはずさんなようです。

365
Fletcher Moore

数年後、今では公式により良い解決策があります。 DOM4ミューテーションオブザーバ は、廃止予定のDOM3ミューテーションイベントに代わるものです。それらは現在 現在のブラウザMutationObserverとして(または古いバージョンのChromeではベンダー接頭辞WebKitMutationObserverとして)実装されています。

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // fired when a mutation occurs
    console.log(mutations, observer);
    // ...
});

// define what element should be observed by the observer
// and what types of mutations trigger the callback
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

この例では、documentとそのサブツリー全体に対するDOMの変更を監視し、構造的な変更と同様に要素の属性に対する変更でも起動します。ドラフト仕様には、有効な 変換リスナープロパティ の完全なリストがあります。

childList

  • ターゲットの子供への突然変異が観察される場合はtrueに設定します。

属性

  • ターゲットの属性への突然変異を観察する場合はtrueに設定します。

characterData

  • ターゲットのデータへの突然変異を観察する場合はtrueに設定します。

サブツリー

  • 突然変異をターゲットにするだけでなく、ターゲットの子孫も観察する場合はtrueに設定します。

attributeOldValue

  • trueがtrueに設定され、突然変異が記録される必要がある前にターゲットの属性値が設定されている場合はattributesに設定します。

characterDataOldValue

  • trueがtrueに設定されていて、突然変異が記録される必要がある前にターゲットのデータをcharacterDataに設定します。

attributeFilter

  • すべての属性の変更を監視する必要があるとは限らない場合は、(名前空間なしで)属性のローカル名のリストに設定します。

(このリストは2014年4月現在のものです。変更については仕様を確認してください。)

441
apsillers

編集

この回答は現在非推奨です。 apsillers の答えを参照してください。

これはChromeの拡張機能のためのものであるため、標準のDOMイベントDOMSubtreeModifiedを使用することもできます。ブラウザ間でこの イベント のサポートを参照してください。 1.0からChromeでサポートされています。

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("tree changed");
});

実用例 はこちら

203
Anurag

多くのサイトはAJAXを使ってコンテンツを動的に追加/表示/変更します。サイト内ナビゲーションの代わりに使用されることがあるので、現在のURLはプログラム的に変更され、この場合ページはリモートサーバーから完全に取得されないため、コンテンツスクリプトはブラウザによって自動的に実行されません。


コンテンツスクリプト で利用可能なページ変更を検出するための通常のJSメソッド。


拡張機能固有: background / event page でURLの変更を検出します。

ナビゲーションを扱うための高度なAPIがあります: webNavigationwebRequest 、しかし我々は単純な chrome.tabs.onUpdatedコンテンツスクリプトへのメッセージ

  • manifest.json:
    背景/イベントページ を宣言
    コンテンツスクリプト を宣言する
    "tabs"permission を追加してください。

  • background.js

    var rxLookfor = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/;
    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
        if (rxLookfor.test(changeInfo.url)) {
            chrome.tabs.sendMessage(tabId, 'url-update');
        }
    });
    
  • content.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        if (msg === 'url-update') {
            doSomething();
        }
    });
    
40
wOxxOm

あなたがdivを変更している方法に応じて別のアプローチ。 JQueryを使用してdivの内容をそのhtml()メソッドで変更する場合は、そのメソッドを拡張して、htmlをdivに入れるたびに登録関数を呼び出すことができます。

(function( $, oldHtmlMethod ){
    // Override the core html method in the jQuery object.
    $.fn.html = function(){
        // Execute the original HTML method using the
        // augmented arguments collection.

        var results = oldHtmlMethod.apply( this, arguments );
        com.invisibility.elements.findAndRegisterElements(this);
        return results;

    };
})( jQuery, jQuery.fn.html );

Html()の呼び出しを傍受し、これを使用して登録関数を呼び出します。これは、コンテキストで新しいコンテンツを取得するターゲット要素を参照してから、呼び出しを元のjquery.html()関数に渡します。 JQueryはメソッドの連鎖に使用することを期待しているため、元のhtml()メソッドの結果を返すことを忘れないでください。

メソッドのオーバーライドと拡張の詳細については、 を参照してください。 jQuery-Methods.htm 、ここでクロージャ関数を省略しました。 JQueryのサイトにあるプラグインのチュートリアルも調べてください。

27
Zac Imboden

MutationObserver API によって提供される「生の」ツールに加えて、DOM変異を扱うための「便利な」ライブラリがあります。

考慮してください。MutationObserverは、各DOMの変更をサブツリーで表します。たとえば、ある要素が挿入されるのを待っているのであれば、それはmutations.mutation[i].addedNodes[j]の子の奥深くにあるかもしれません。

もう一つの問題は、突然変異に反応してあなた自身のコードがDOMを変更する時です - あなたはしばしばそれを除外したいと思います。

このような問題を解決する優れた便利なライブラリは mutation-summary です(免責事項:私は作者ではありません、満足しているユーザーです)。あなたが興味を持っているものの、そして正確にそれを手に入れよう。

ドキュメントからの基本的な使用例:

var observer = new MutationSummary({
  callback: updateWidgets,
  queries: [{
    element: '[data-widget]'
  }]
});

function updateWidgets(summaries) {
  var widgetSummary = summaries[0];
  widgetSummary.added.forEach(buildNewWidget);
  widgetSummary.removed.forEach(cleanupExistingWidget);
}
6
Xan