DOM要素がページに追加されたときに実行するように選択した機能が必要です。これはブラウザ拡張機能のコンテキストにあるため、ウェブページは私とは関係なく実行され、ソースを変更することはできません。ここに私のオプションは何ですか?
理論setInterval()
的には、要素の存在を継続的に検索し、要素が存在する場合にアクションを実行するために使用できるだけだと思いますが、より良いアプローチが必要です。
DOM要素がページに追加されたときに実行するように選択した機能が必要です。これはブラウザ拡張機能のコンテキストにあるため、ウェブページは私とは関係なく実行され、ソースを変更することはできません。ここに私のオプションは何ですか?
理論setInterval()
的には、要素の存在を継続的に検索し、要素が存在する場合にアクションを実行するために使用できるだけだと思いますが、より良いアプローチが必要です。
回答:
警告!
この回答は古くなっています。DOMレベル4にはMutationObserverが導入され、廃止されたミューテーションイベントの効果的な置き換えを提供します。ここに提示されたものよりも良い解決策については、この回答を参照してください。真剣に。100ミリ秒ごとにDOMをポーリングしないでください。CPUパワーを浪費し、ユーザーはあなたを嫌います。
以来突然変異イベントは 2012年に廃止予定、とあなたは、彼らが他の誰かのコードによって追加されているので、挿入された要素を制御することはできませんして、あなたの唯一のオプションは、継続的に彼らのためにチェックすることです。
function checkDOMChange()
{
// check for any new element being inserted here,
// or a particular node being modified
// call the function again after 100 milliseconds
setTimeout( checkDOMChange, 100 );
}
この関数が呼び出されると、100ミリ秒ごとに実行されます。これは、1秒の1/10(1/10)です。リアルタイムの要素観測が必要でない限り、それで十分です。
MutationObserver()
:davidwalsh.name/mutationobserver-api
Event.ADDED_TO_STAGE
か?
実際の答えは「ミューテーションオブザーバーを使用する」です(この質問で概説しています:HTML要素がDOMに動的に追加されているかどうかを判断します)。ただし、サポート(特にIEで)は制限されています(http://caniuse.com/mutationobserver) 。
したがって、実際の実際の答えは「ミューテーションオブザーバーを使用することです...最終的には。しかし、今のところホセファエティの答えを使用してください」:)
ミューテーションイベントの廃止との出現の間MutationObserver
に、特定の要素がDOMに追加されたときに通知を受ける効率的な方法は、CSS3アニメーションイベントを利用することでした。
ブログ投稿を引用するには:
DOMノード挿入イベントを受け取りたいDOM要素を(選択したCSSセレクターを介して)対象とするCSSキーフレームシーケンスを設定します。
私は比較的無害でほとんど使用されていないcssプロパティを使用しました。意図したページスタイルの混乱を避けるために、アウトラインカラーを使用しました。コードは一度クリッププロパティを対象としたものですが、バージョン11のIEではアニメーション化できなくなりました。とはいえ、アニメーション化できるプロパティはすべて機能するので、好きなものを選択してください。次に、ノード挿入を処理するためのデリゲートとして使用するドキュメント全体のanimationstartリスナーを追加しました。アニメーションイベントには、animationNameというプロパティがあり、アニメーションを開始したキーフレームシーケンスを示します。animationNameプロパティがノードの挿入に追加したキーフレームシーケンス名と同じであることを確認してください。
animationstart
、jsbin.com/netuquralu/1/edit。
livequery
jQuery 用のプラグインを使用できます。次のようなセレクター式を指定できます。
$("input[type=button].removeItemButton").livequery(function () {
$("#statusBar").text('You may now remove items.');
});
removeItemButton
クラスのボタンが追加されるたびに、ステータスバーにメッセージが表示されます。
効率の点ではこれを避けたいと思うかもしれませんが、いずれの場合でも、独自のイベントハンドラーを作成する代わりにプラグインを利用できます。
再訪した答え
上記の回答は、アイテムがプラグインを介してDOMに追加されたことを検出することのみを目的としています。
ただし、ほとんどのjQuery.on()
場合、次のようなアプローチがより適切です。
$("#myParentContainer").on('click', '.removeItemButton', function(){
alert($(this).text() + ' has been removed');
});
たとえば、クリックに応答する必要がある動的コンテンツがある場合は、を使用してイベントを親コンテナにバインドするのが最善jQuery.on
です。
ETA 24 Apr 17
私はこれをもっと簡潔にするためにasync
/ await
マジックでこれを少し単純化したかった:
同じ約束されたオブザーバブルを使用する:
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
呼び出し関数は次のように単純にすることができます。
const waitForMutation = async () => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await startObservable(someDomNode)
return results
} catch (err) {
console.error(err)
}
}
タイムアウトを追加したい場合は、ここにPromise.race
示すように単純なパターンを使用できます。
const waitForMutation = async (timeout = 5000 /*in ms*/) => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await Promise.race([
startObservable(someDomNode),
// this will throw after the timeout, skipping
// the return & going to the catch block
new Promise((resolve, reject) => setTimeout(
reject,
timeout,
new Error('timed out waiting for mutation')
)
])
return results
} catch (err) {
console.error(err)
}
}
元の
ライブラリなしでこれを行うことはできますが、ES6のものを使用する必要があるため、互換性の問題に注意してください(つまり、オーディエンスが主にアーミッシュ、ラディット、またはさらに悪い場合はIE8ユーザーの場合)。
まず、MutationObserver APIを使用してオブザーバーオブジェクトを作成します。このオブジェクトをpromiseでラップresolve()
し、コールバックが発生すると(h / t davidwalshblog)ミューテーションに関するdavid walsh ブログ記事:
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
次に、を作成しgenerator function
ます。これらをまだ使用していない場合は、見逃していることになりますが、簡単な概要は次のとおりです。同期関数のように実行され、yield <Promise>
式が見つかると、ブロックされない方法でプロミスになるのを待ちます。 (ジェネレーターはこれ以上のことを行いますが、これは私たちがここで興味を持っているものです)
// we'll declare our DOM node here, too
let targ = document.querySelector('#domNodeToWatch')
function* getMutation() {
console.log("Starting")
var mutations = yield startObservable(targ)
console.log("done")
}
ジェネレータについてのトリッキーな部分は、ジェネレータが通常の関数のように「復帰」しないことです。そこで、ヘルパー関数を使用して、ジェネレーターを通常の関数のように使用できるようにします。(再び、h / tからdwbへ)
function runGenerator(g) {
var it = g(), ret;
// asynchronously iterate over generator
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
// poor man's "is it a promise?" test
if ("then" in ret.value) {
// wait on the promise
ret.value.then( iterate );
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
次に、予想されるDOM変異が発生する前の任意の時点で、単にを実行しrunGenerator(getMutation)
ます。
これで、DOMミューテーションを同期スタイルの制御フローに統合できます。なんてことだ。
ブラウザのサポートが一般的になると、ミューテーションオブザーバーの利用を開始する優れた方法のように見える、Arriveと呼ばれる有望なJavaScriptライブラリがあります。
それを正確に行うこのプラグインをチェックしてください-jquery.initialize
.each関数とまったく同じように機能します。違いは、入力したセレクターを受け取り、このセレクターに一致する将来追加される新しい項目を監視して初期化することです。
初期化は次のようになります
$(".some-element").initialize( function(){
$(this).css("color", "blue");
});
しかし、新しい要素マッチング.some-element
セレクターがページに表示されると、すぐに初期化されます。
新しいアイテムを追加する方法は重要ではありません。コールバックなどを気にする必要はありません。
したがって、次のような新しい要素を追加する場合:
$("<div/>").addClass('some-element').appendTo("body"); //new element will have blue color!
即座に初期化されます。
プラグインはに基づいています MutationObserver
純粋なJavaScriptソリューション(なしjQuery
):
const SEARCH_DELAY = 100; // in ms
// it may run indefinitely. TODO: make it cancellable, using Promise's `reject`
function waitForElementToBeAdded(cssSelector) {
return new Promise((resolve) => {
const interval = setInterval(() => {
if (element = document.querySelector(cssSelector)) {
clearInterval(interval);
resolve(element);
}
}, SEARCH_DELAY);
});
}
console.log(await waitForElementToBeAdded('#main'));