基本的に、内容が変更されたときにスクリプトを実行したいと考えていますDIV
。スクリプトは別のもの (Chrome 拡張機能のコンテンツ スクリプトと Web ページ スクリプト) であるため、DOM 状態の変化を簡単に観察する方法が必要です。ポーリングを設定できましたが、ずさんなようです。
5 に答える
長い間、DOM3ミューテーションイベントは利用可能な最善のソリューションでしたが、パフォーマンス上の理由から非推奨になりました。DOM4 Mutation Observersは、廃止されたDOM3ミューテーションイベントの代わりになります。それらは現在、次のように(または古いバージョンのChromeではベンダープレフィックスとして)最新のブラウザに実装されています。MutationObserver
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
//...
});
この例では、サブツリー全体でのDOMの変更をリッスンしdocument
、構造の変更だけでなく要素属性の変更でも起動します。ドラフト仕様には、有効なミューテーションリスナープロパティの完全なリストがあります。
childList
true
ターゲットの子への突然変異が観察される場合に設定します。属性
true
ターゲットの属性への変異が観察される場合に設定します。characterData
true
ターゲットのデータへの変異を観察する場合に設定します。サブツリー
true
ターゲットだけでなく、ターゲットの子孫への突然変異が観察される場合に設定します。attributeOldValue
- ミューテーションを記録する必要がある前に、
true
ifに設定してtrueに設定し、ターゲットの属性値を設定します。attributes
characterDataOldValue
- ミューテーションを記録する必要がある前に、
true
ifに設定してtrueに設定し、ターゲットのデータを設定します。characterData
attributeFilter
- すべての属性の変更を監視する必要がない場合は、属性のローカル名(名前空間なし)のリストに設定します。
(このリストは2014年4月現在のものです。仕様に変更がないか確認してください。)
多くのサイトでは、コンテンツを動的に追加、表示、変更するために AJAX/XHR/fetch を使用し、サイト内ナビゲーションの代わりに window.history API を使用しているため、現在の URL はプログラムによって変更されます。このようなサイトは、Single Page Application の略で SPA と呼ばれます。
ページ変更を検出する通常の JS メソッド
MutationObserver ( docs ) を使用して、文字通り DOM の変更を検出します。
情報/例:
URL も変更された場合にのみ変更に反応する軽量オブザーバー:
let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; onUrlChange(); } }).observe(document, {subtree: true, childList: true}); function onUrlChange() { console.log('URL changed!', location.href); }
DOM イベントを送信してコンテンツの変更を通知するサイトのイベント リスナー:
pjax:end
document
GitHub などの多くの pjax ベースのサイトで使用されている場合は、pjax ロードの前後に jQuery を実行する方法を
参照してください。message
window
Chrome ブラウザの Google 検索などで使用されます。「Chrome 拡張機能が Google 検索の更新を検出する
」を参照してください。yt-navigate-finish
YouTube で使用されている、YouTube でページ ナビゲーションを検出し、その外観をシームレスに変更する方法を
参照してください。
setInterval による DOM の定期的なチェック:
明らかにこれは、ID/セレクターによって識別される特定の要素が表示されるのを待っている場合にのみ機能し、何らかのフィンガープリンティングを発明しない限り、新しく動的に追加されたコンテンツを普遍的に検出することはできません。既存のコンテンツ。クローキング履歴 API :
let _pushState = History.prototype.pushState; History.prototype.pushState = function (state, title, url) { _pushState.call(this, state, title, url); console.log('URL changed', url) };
hashchange、popstateイベントのリッスン:
window.addEventListener('hashchange', e => { console.log('URL hash changed', e); doSomething(); }); window.addEventListener('popstate', e => { console.log('State changed', e); doSomething(); });
PS これらのメソッドはすべて、WebExtension のcontent scriptで使用できます。これは、我々が見ているケースが history.pushState または replaceState によって URL が変更された場合であり、ページ自体は同じコンテンツ スクリプト環境で同じままであったためです。
div の変更方法に応じた別のアプローチ。JQuery を使用して html() メソッドで div のコンテンツを変更している場合、そのメソッドを拡張して、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() 関数への呼び出しを渡します。元の html() メソッドの結果を返すことを忘れないでください。これは、JQuery がメソッド チェーンのためにそれを想定しているためです。
メソッドのオーバーライドと拡張の詳細については、http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htmを確認してください。クロージャー機能をくわえました。また、JQuery のサイトにあるプラグインのチュートリアルもご覧ください。
MutationObserver
APIによって提供される「生の」ツールに加えて、DOM ミューテーションを操作するための「便利な」ライブラリが存在します。
考慮事項: MutationObserver は、各 DOM 変更をサブツリーで表します。たとえば、特定の要素が挿入されるのを待っている場合、その要素は の子の奥深くにある可能性がありmutations.mutation[i].addedNodes[j]
ます。
もう 1 つの問題は、ミューテーションに反応して独自のコードが 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);
}