DOM'a belirli bir sınıfın jquery algılayan div'i eklendi


92

.on()Sayfa yüklendikten sonra oluşturulan div olaylarını bağlamak için kullanıyorum . Tıklama, fare girişi için iyi çalışıyor ... ama sınıfımın yeni bir div'i sınıfının ne zaman eklendiğini bilmem gerekiyor. Ben bunu arıyorum:

$('#MyContainer').on({

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

}, '.MyClass');

Bunu nasıl yaparım? Tüm uygulamamı bir eklenti olmadan yazmayı başardım ve bu şekilde kalmasını istiyorum.

Teşekkürler.


Öğeleri oluşturan kendi kodunuz mu? Öyleyse, onu oluşturduğunuz anda kontrol edebilir ve buna göre hareket edebilirsiniz.
Surreal Dreams

Evet, bu doğru ama .on () ile olayları document.ready adresinde bağlayabilirim ve sonra HTML'yi oluşturduğumda bağlama konusunda endişelenmeme gerek kalmaz. DoSomething ile aynı davranışı arıyorum.
frenchie

$ ("div / seçiciniz"). hasClass ("Sınıfım"); bir div'in belirli bir sınıfa sahip olup olmadığını kontrol etmek için. Sanırım bu api'yi kendi kullanımınıza sunabilirsiniz.
KBN

.on () yalnızca etkinlikler içindir. Özel bir etkinlik ayarlayabilirsiniz, ancak yeni öğeler oluşturduğunuzda yine de bu etkinliği tetiklemeniz gerekir.
Surreal Dreams

Yanıtlar:


105

Daha önce domManip, jQuery'nin tüm jQuery dom manipülasyonlarını yakalamak ve hangi öğelerin nereye yerleştirildiğini görmek için bir yöntem kullanılıyordu, ancak jQuery ekibi bunu jQuery 3.0 + 'da kapattı çünkü jQuery yöntemlerine bu şekilde bağlanmak genellikle iyi bir çözüm değil ve onlar' dahili domManipyöntemin artık çekirdek jQuery kodunun dışında kullanılamayacağı şekilde yapılmıştır.

Daha önce olduğu gibi, Mutasyon Olayları da kullanımdan kaldırıldı.

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

bundan kaçınılmalıdır ve bugün bunun yerine Mutasyon Gözlemcileri kullanılmalıdır, bu şekilde çalışır

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 ve webkit hemen hemen iyi durumda olmalı, ancak bunun için destek IE'de biraz zayıf. IE9'da çalışmalı, ancak muhtemelen IE8'de o kadar fazla değil. Geçici çözümler gördüğümü biliyorum ve bunu IE'de gerçekten test etmedim, bu yüzden önce test edin, çalışmıyorsa bir çözüm olup olmadığını görün. Buraya IE desteği ekleyen gibi görünen bir eklenti var , ancak henüz denemedim, bir Google aramasında buldum.
adeneo

2
Başlangıçta cevabınızı kullandım, ancak tarayıcılar arası çalışmıyor olması bir sorundu. Sonra, ilk etapta bu sorunu önlemek için çabucak bir çözüm buldum. Ve sonra, birkaç hafta önce, düğüm eklemeyi algılama sorunu kodumda tekrar geri geldi. Bu sefer, cevabımda gönderdiğim kod TAM OLARAK olması gerektiği gibi çalışıyor, tarayıcılar arası ve hatalı değil. Bu yüzden cevabımı kabul edildi olarak değiştirdim; SO böyle çalışır, OP hangi cevabı kabul edeceğine karar verir ve kalabalık cevaplara oy verir. Zamanla insanlar oy verecek ve hangi cevabın kendilerine en uygun olduğuna karar verecekler.
frenchie

2
Ayrıca, günümü kurtaran yüksek kaliteli cevaplarla bana defalarca yardım ettiğinizi söylemek istedim. Kabul edilen cevabı benimkiyle değiştirmek tamamen koda ve çözmem gereken soruna nasıl uyduğuna bağlıdır.
frenchie

Bu kodla "Yakalanmamış TypeError: Tanımsız 'içeriğinin' özelliği okunamıyor"
gordie

53

İşte tam olarak bunu yapan eklentim - jquery.initialize

Kullanım, .eachişlevi kullandığınızla aynıdır , ancak öğedeki işlevle, bunun .initializefarkı, .eachgelecekte ek bir kod olmadan eklenen öğeleri de başlatmasıdır - AJAX veya başka bir şeyle eklerseniz ekleyin.

Initialize, .each işleviyle tam olarak aynı sözdizimine sahiptir

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

Ama şimdi yeni eleman eşleşen .some-element seçici sayfada görünecekse, anında başlatılacaktır. Yeni öğenin eklenme şekli önemli değildir, herhangi bir geri aramayla ilgilenmenize gerek yoktur.

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

Eklenti, MutationObserver


Çok teşekkür ederim.
Brandon Harris

başlatma nasıl durdurulur? Aradığım şeyler eklendiğinde izlemeyi bırakmak istiyorum ...
Evgeny Vostok

$ (". some-element"). initialize [..] kullanımdan kaldırıldı. $ .İnitialize (". AddDialog", function () {$ ('. NoData'). Hide ();}); yerine.
Heimi

.initializeİşlevin callback yalnızca dinamik olarak eklenen öğeler için (örneğin Ajax aracılığıyla) çalıştırılması ve sayfa ilk yüklendiğinde zaten mevcut olan öğeler için geri aramayı atlamak mümkün müdür ? Bunu optionsbaşarmak için bir parametre eklemeye çalışıyorum , ancak şu ana kadar bunu çalıştırmadım.
Nevermore

Bununla ilgili olarak github'a sorun ekleyebilirsiniz. Şimdilik, teknik olarak yapabilirdin$('.myClass').addClass('ignore-initialize'); $.initialize('.myClass:not(.ignore-initialize)', callback);
Adam Pietrasiak

19

Bunu ve diğer birkaç gönderiyi inceledikten sonra, her birinin en iyisi olduğunu düşündüğüm şeyi, bir öğe sınıfının ne zaman eklendiğini tespit etmeme ve ardından bu öğeler üzerinde hareket etmeme izin veren basit bir şeye dönüştürmeye çalıştım .

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);
});

Benim için önemli olan bu, a) hedef öğenin "eklenen Düğümler" içinde herhangi bir derinlikte bulunmasına ve b) yalnızca başlangıçta eklendiğinde öğeyle başa çıkma becerisine (tüm belge ayarını aramaya gerek yok veya "önceden işlenmiş" i yok saymaya gerek yok) bayraklar).


1
Durumunuz olmalıdır if(mutation.addedNodes.length)çünkü addedNodesve removedNodesdiziler içinde her zaman vardır mutationÇeşidi childList(IE11, Chrome53, FF49 kontrol). Yine de +1, çünkü addedNodesdikkate alınan tek cevap sizinki ( callbacksadece bir düğüm eklendiğinde çağrılır); sadece bu konu üzerinde değil, diğer birçok konu üzerinde. callbackDüğüm siliniyor olsa bile, diğer herkes sadece tüm mutasyonları çağırıyor .
Vivek Athalye

17

3 yıllık deneyimimden sonra, "DOM'a eklenen belirli bir sınıfın öğesi" ni şu şekilde dinlerim : jQuery html()işlevine şunun gibi bir kanca eklemeniz yeterlidir :

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);

Bu, benim yaptığım jQuery kullanıyorsanız çalışır. Ve tarayıcılar DOMNodeInsertedarası uyumlu olmayan tarayıcıya özgü etkinliğe dayanmaz . Aynı uygulamayı şunun için de ekledim:.prepend()

Genel olarak, bu benim için bir cazibe gibi çalışıyor ve umarım sizin için de.


6
Hmm - htmlGenel olarak yalnızca "jQuery kullanarak" değil, DOM'u değiştirmek için yalnızca jQuery'nin yardımcısını kullanıyorsanız bunun işe yarayacağını açıklığa kavuşturabilirim . Örneğin kullanılarak eklenen öğeler jQuery.appendbu etkinliği tetiklemez.
iameli

1
Evet, bu yüzden aynı uygulamayı .preprend () ile eklediğimi ve .append () kullanıyorsanız aynı şeyi .append () ile de yapın
frenchie

CSS3 animasyonlarını kullanan çok daha hızlı bir yaklaşım var . Açık kaynak kütüphanesi aynı zamanda çok daha basit bir koda da sahiptir:insertionQ('#intercom-container').every(function(/element){ element.style.display = 'none'; });
Dan Dascalescu

3
Neden olumsuz oy? Bu aslında işe yarıyor: eklenti yok ve hacky setTimeout işlevi yok.
frenchie

2
Olumlu oy verildi - bu geçerli bir seçenektir - neden dünyada (!!!) bu olumsuz oy verildi ?????? Dan, CSS3 Animasyonları XBC değildir: caniuse.com/#search=keyframes ; davidwalsh.name/detect-node-insertion .
Cody

6

mutasyon olaylarını kullanabilirsin

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

DÜZENLE

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

Kullanımdan Kaldırıldı Bu özellik Web'den kaldırılmıştır. Bazı tarayıcılar hala desteklese de, bırakılma sürecindedir. Eski veya yeni projelerde kullanmayınız. Bunu kullanan sayfalar veya Web uygulamaları her an bozulabilir.

Mutasyon Gözlemcileri, DOM4'teki mutasyon olayları için önerilen ikamedir. Firefox 14 ve Chrome 18'e dahil edilecekler.

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

MutationObservergeliştiricilere bir DOM'daki değişikliklere tepki vermenin bir yolunu sağlar. DOM3 Olayları spesifikasyonunda tanımlanan Mutasyon Olaylarının yerini alacak şekilde tasarlanmıştır.

Örnek kullanım

Aşağıdaki örnek, http://hacks.mozilla.org/2012/05/dom-mutationobserver-reacting-to-dom-changes-without-killing-browser-performance/ adresinden alınmıştır .

// 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
Mutasyon olayları, mdn'ye göre , MutationObservers lehine , neredeyse tamamen reddedildi
Olga

IE10 artık EOL olduğuna göre, MutationObserver'ın yaygın olarak desteklendiğini söylemek neredeyse güvenli olacaktır .
rymo

0

Adeneo'nun cevabına iki ekleme:

(1) çizgiyi değiştirebiliriz

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

İçin

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

Yani "Uncaught TypeError: Cannot read property 'contains' of undefined"hatayı görmeyeceğiz .

(2) bir eklenti subtree: trueolarak configardışık tüm ilave elemanlarında ilave düğümleri bulmak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.