特定のクラスのdivを検出するjqueryがDOMに追加されました


90

.on()ページの読み込み後に作成されるdivのイベントをバインドするために使用しています。クリック、mouseenterで問題なく動作します...しかし、クラスMyClassの新しいdivがいつ追加されたかを知る必要があります。私はこれを探しています:

$('#MyContainer').on({

  wascreated: function () { DoSomething($(this)); }

}, '.MyClass');

どうすればよいですか?プラグインなしでアプリ全体を作成できたので、そのままにしておきたいと思います。

ありがとう。


要素を生成しているのはあなた自身のコードですか?もしそうなら、あなたはそれを作成するときにチェックし、それに応じて行動することができます。
シュールな夢2012

はい、それは本当ですが、.on()を使用すると、document.readyでイベントをバインドでき、HTMLを生成するときにバインドについて心配する必要がありません。DoSomethingで同じ動作を探しています。
フレンチブルドッグ2012年

$( "div / your-selector")。hasClass( "MyClass");を使用できます。divに特定のクラスがあるかどうかを確認します。このAPIを使用できると思います。
KBN 2012年

.on()はイベント専用です。カスタムイベントを設定することもできますが、新しい要素を作成したときにそのイベントをトリガーする必要があります。
シュールな夢2012

回答:


102

以前は、jQueryのdomManipメソッドにフックしてすべてのjQuery dom操作をキャッチし、挿入された要素などを確認できましたが、jQuery 3.0以降では、jQueryメソッドにフックするのは一般的に適切なソリューションではないため、jQueryチームはそれをシャットダウンしました。内部domManipメソッドがコアjQueryコードの外部で使用できなくなるようにしました。

以前のように、ミューテーションイベントも非推奨になりました。

$(document).on('DOMNodeInserted', function(e) {
    if ( $(e.target).hasClass('MyClass') ) {
       //element with .MyClass was inserted.
    }
});

これは回避する必要があり、今日は代わりにMutationObserversを使用する必要があります。これは次のように機能します。

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation)
        if (mutation.addedNodes && mutation.addedNodes.length > 0) {
            // element added to DOM
            var hasClass = [].some.call(mutation.addedNodes, function(el) {
                return el.classList.contains('MyClass')
            });
            if (hasClass) {
                // element has class `MyClass`
                console.log('element ".MyClass" added');
            }
        }
    });
});

var config = {
    attributes: true,
    childList: true,
    characterData: true
};

observer.observe(document.body, config);

FirefoxとWebkitはほぼ問題ないはずですが、IEではこれに対するサポートがやや不十分です。IE9では機能するはずですが、IE8ではおそらくそれほど機能しません。私は回避策を見たことがあることを知っていますが、IEでこれを実際にテストしていないので、最初にテストし、機能しない場合は回避策があるかどうかを確認します。ここにIEサポートを追加しているように見えるプラグインがありますが、試したことがなく、Google検索で見つかりました。
adeneo 2012年

2
私は最初にあなたの答えを使用しましたが、それがクロスブラウザで機能していなかったという事実は問題でした。次に、そもそもこの問題を回避するための回避策をすぐに見つけました。そして、数週間前に、ノードの挿入を検出するというこの問題が私のコードで再び発生しました。今回、私の回答に投稿したコードは、クロスブラウザーでバグがなく、正確に機能します。だから私は自分の答えを受け入れられたものとして動かしたのです。それがSOの仕組みであり、OPは彼が受け入れる回答を決定し、群衆は回答に投票します。時間が経つにつれて、人々は投票し、どの答えが自分に最も適しているかを決定します。
フレンチブルドッグ2015年

2
また、質の高い回答で何度か助けてくれて、私の一日を救ってくれたと言いたいです。受け入れられた答えを私のものに変更することは、純粋にコードとそれが私が解決しなければならなかった問題にどのように適合するかに基づいています。
フレンチブルドッグ2015年

「キャッチされない例外TypeErrorを:プロパティ未定義の『が含ま』を読み込めません」だ。このコードで
gordie

53

これが正確にそれを行う私のプラグインです--jquery.initialize

使用法は.eachfunctionを使用する場合と同じですが、.initializefunction on elementを使用.eachすると、AJAXなどで追加するかどうかに関係なく、追加のコードなしで将来追加される要素も初期化されるという違いがあります。

初期化は、.each関数とまったく同じ構文を持っています

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

しかし、.some-elementセレクターに一致する新しい要素がページに表示されると、すぐに初期化されます。新しいアイテムを追加する方法は重要ではありません。コールバックなどを気にする必要はありません。

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

プラグインはに基づいています MutationObserver


どうもありがとうございます。
ブランドン・ハリス

初期化を停止する方法は?探していたものが追加されたら、視聴をやめたい...
Evgeny Vostok 2017

$( "。some-element")。initialize [..]は非推奨です。$ .initialize( "。addDialog"、function(){$( '。noData')。hide();});を使用します。代わりに。
ヘイミ2018年

動的に追加された要素(Ajaxなど)に対してのみ.initialize関数を実行し、ページが最初に読み込まれたときにすでに存在する要素のコールバックをスキップすることは可能ですか?これを実現するためににパラメータを追加しようとしていますが、これまでのところ、これを機能させることができません。callback options
ネバーモア2018

あなたはそれについてgithubに問題を追加することができます。今のところ、技術的には次のことができます$('.myClass').addClass('ignore-initialize'); $.initialize('.myClass:not(.ignore-initialize)', callback);
pie6k 2018年

19

これと他のいくつかの投稿を確認した後、要素のクラスが挿入されたことを検出し、それらの要素に作用することを可能にする単純なものに、それぞれの最良だと思うものを抽出しようとしました。

function onElementInserted(containerSelector, elementSelector, callback) {

    var onMutationsObserved = function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length) {
                var elements = $(mutation.addedNodes).find(elementSelector);
                for (var i = 0, len = elements.length; i < len; i++) {
                    callback(elements[i]);
                }
            }
        });
    };

    var target = $(containerSelector)[0];
    var config = { childList: true, subtree: true };
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    var observer = new MutationObserver(onMutationsObserved);    
    observer.observe(target, config);

}

onElementInserted('body', '.myTargetElement', function(element) {
    console.log(element);
});

私にとって重要なことは、これにより、a)ターゲット要素が「addedNodes」内の任意の深さに存在し、b)最初に挿入されたときにのみ要素を処理する機能(ドキュメント設定全体を検索したり、「処理済み」を無視したりする必要がない)フラグ)。


1
あなたの条件はする必要がありますif(mutation.addedNodes.length)ので、addedNodes及びremovedNodes配列は常にあるmutationタイプのchildList(IE11、Chrome53、FF49でチェック)。それでも+1、addedNodes考慮される唯一の答えはあなたのものだからです(callbackノードが追加されたときにのみ呼び出されます)。このスレッドだけでなく、他の多くのスレッドでも。callbackノードが削除されている場合でも、他のすべての人はすべてのミューテーションに対してを呼び出しています。
Vivek Athalye 2016

17

3年後の経験で、これが「DOMに追加された特定のクラスの要素」を聞く方法です。次のhtml()ように、jQuery関数にフックを追加するだけです。

function Start() {

   var OldHtml = window.jQuery.fn.html;

   window.jQuery.fn.html = function () {

     var EnhancedHtml = OldHtml.apply(this, arguments);

     if (arguments.length && EnhancedHtml.find('.MyClass').length) {

         var TheElementAdded = EnhancedHtml.find('.MyClass'); //there it is
     }

     return EnhancedHtml;
   }
}

$(Start);

これは、私が行っているjQueryを使用している場合に機能します。またDOMNodeInserted、クロスブラウザ互換ではないブラウザ固有のイベントに依存しません。同じ実装を追加しました.prepend()

全体として、これは私にとって、そしてうまくいけばあなたにとっても魅力のように機能します。


6
うーん-これはhtml、一般に「jQueryを使用する」だけでなく、jQueryのヘルパーを使用してDOMを変更する場合にのみ機能することを明確にします。たとえば、jQuery.appendを使用して追加された要素は、このイベントをトリガーしません。
iameli 2015年

1
はい。そのため、.preprend()で同じ実装を追加し、.append()を使用する場合は、.append()で同じことを行うことを明確にしました
Frenchie 2015年

CSS3アニメーションを使用した、はるかに高速なアプローチがあります。:オープンソースのライブラリもはるかに簡単コードに貸すinsertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
ダンDascalescu

3
なぜ反対票を投じるのですか?これは実際に機能します。プラグインもハッキーなsetTimeout関数もありません。
フレンチブルドッグ2015

2
賛成-これは有効なオプションです-なぜ世界で(!!!)これが反対されたのですか???? ダン、CSS3アニメーションはXBCではありません:caniuse.com/#search=keyframes ; davidwalsh.name/detect-node-insertion
コーディ

6

突然変異イベントを使用できます

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents

編集

MDNから:https//developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

非推奨この機能はWebから削除されました。一部のブラウザはまだそれをサポートしているかもしれませんが、それは削除されている途中です。古いプロジェクトや新しいプロジェクトでは使用しないでください。それを使用しているページやWebアプリはいつでも壊れることがあります。

ミューテーションオブザーバーは、DOM4のミューテーションイベントの代替案です。これらはFirefox14とChrome18に含まれる予定です。

https://developer.mozilla.org/en/docs/Web/API/MutationObserver

MutationObserver開発者にDOMの変更に対応する方法を提供します。これは、DOM3イベント仕様で定義されているミューテーションイベントの代わりとして設計されています。

使用例

次の例は、http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/から抜粋したものです。

// select the target node
var target = document.querySelector('#some-id');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);

// later, you can stop observing
observer.disconnect();

2
mdnによると、MutationObservers
Olga

IE10がEOLになったので、MutationObserverが広くサポートされていると言っても過言ではありません。
rymo 2016年

0

adeneoの答えへの2つの追加:

(1)行を変更できます

return el.classList.contains('MyClass');

if( el.classList ) {
    return el.classList.contains('MyClass');
} else {
    return false;
}

したがって、"Uncaught TypeError: Cannot read property 'contains' of undefined"エラーは表示されません。

(2)追加subtree: trueconfigて、追加されたすべての要素で追加されたノードを再帰的に検索します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.