JavaScript / jQuery DOM değişiklik dinleyicisi var mı?


402

Temelde ben bir komut dosyası bir DIVdeğişiklik içeriği yürütmek istiyorum . Komut dosyaları ayrı olduğundan (Chrome uzantısı ve web sayfası komut dosyasında içerik komut dosyası), DOM durumundaki değişiklikleri gözlemlemenin bir yoluna ihtiyacım var. Oylama ayarlayabilirdim ama bu özensiz görünüyor.

Yanıtlar:


488

Uzun zamandır, DOM3 mutasyon olayları mevcut en iyi çözümdü, ancak performans nedenlerinden dolayı kullanımdan kaldırıldı. DOM4 Mutasyon Gözlemcileri , kullanımdan kaldırılmış DOM3 mutasyon olaylarının yerine geçer. Onlar edilir anda modern tarayıcılarda uygulanmaktadır olarak MutationObserver(ya da satıcı-öneki WebKitMutationObserverChrome eski sürümlerinde):

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

Bu örnek, DOM değişikliklerini documentve tüm alt ağacını dinler ve eleman özelliklerindeki değişikliklerin yanı sıra yapısal değişikliklere de neden olur. Taslak spesifikasyon, geçerli mutasyon dinleyici özelliklerinin tam listesine sahiptir :

öğelistesindebirden

  • Ayarlayın truehedefin çocuklara mutasyonlar gözlenebilir istiyorsak.

Öznitellikler

  • Ayarlayın truehedefin özelliklerine mutasyonlar gözlenebilir istiyorsak.

characterData

  • Ayarlayın truehedefin verilerine mutasyonlar gözlenebilir istiyorsak.

alt ağaç

  • trueSadece mutasyonların değil, aynı zamanda hedefin torunları da gözlemlenecek mutasyonlara ayarlayın .

attributeOldValue

  • Ayarla trueeğer attributesmutasyon ihtiyaçları kaydedilecek önce gerçek ve hedef öznitelik değerine ayarlanır.

characterDataOldValue

  • Ayarla trueeğer characterDatamutasyon ihtiyaçları kaydedilecek önce doğru ve hedef verilerine ayarlanır.

attributeFilter

  • Tüm özellik mutasyonlarına uyulması gerekmiyorsa, özellik yerel adları listesine (ad alanı olmadan) ayarlayın.

(Bu liste Nisan 2014 itibariyle geçerlidir; herhangi bir değişiklik için teknik özellikleri kontrol edebilirsiniz.)


3
@AshrafBashir Örnek Firefox 19.0.2'de iyi çalışıyor görüyorum: ([{}])Konsola kaydedilmiş görüyorum , bu da MutationRecordtıkladığımda beklenenleri gösteriyor . JSFiddle'da geçici bir teknik arıza olabileceğinden lütfen tekrar kontrol edin. Şu anda mutasyon olaylarını desteklemek için tek sürüm olan IE 10'a sahip olmadığım için henüz IE'de test etmedim.
apsillers

1
Ben sadece IE10 + ve çoğunlukla başka bir şey çalışan bir cevap yayınladı.
naugtur

1
Spesifikasyonda artık mutasyon gözlemci seçeneklerini listeleyen yeşil bir kutu yok gibi görünüyor. It does listesine seçenekleri bölümünde 5.3.1 ve ayrıca bunun altında onlara sadece biraz anlatır.
LS

2
@LS Teşekkürler, bağlantıyı güncelledim, yeşil kutu hakkındaki biraz kaldırdım ve tüm listeyi cevabımda düzenledim (sadece gelecekteki bağlantı çürümesi durumunda).
apsillers

3
İşte Can I Use uygulamasından bir tarayıcı uyumluluk tablosu .
bdesham

211

Düzenle

Bu cevap şimdi kullanımdan kaldırıldı. Cevap verenler tarafından verilen cevaba bakınız .

Bu bir Chrome uzantısı için olduğundan, standart DOM etkinliğini de kullanabilirsiniz - DOMSubtreeModified. Tarayıcılarda bu etkinliğin desteğine bakın . 1.0'dan beri Chrome'da desteklenmektedir.

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

Burada çalışan bir örneğe bakın .


Bu etkinliğin belirli seçicilerden sonra bile tetiklenebileceğini fark ettim. Şu anda araştırıyorum.
Peder Rice

9
w3.org/TR/DOM-Level-3-Events/#event-type-DOMSubtreeModified , bu etkinliğin kullanımdan kaldırıldığını söylüyor, bunun yerine ne kullanırız?
Maslow


4
Orada github.com/joelpurra/jquery-mutation-summary temelde jquery kullanıcılar için bu çözer hangi.
Capi Etheriel

1
Chrome uzantıları oluşturuyorsanız, yine de çalışır. paha biçilmez.
concept47

49

Birçok site dinamik olarak içerik eklemek / göstermek / değiştirmek için AJAX kullanır. Bazen site içi gezinme yerine kullanılır, dolayısıyla mevcut URL programlı olarak değiştirilir ve sayfa tamamen uzak sunucudan getirilmediğinden içerik komut dosyaları tarayıcı tarafından otomatik olarak yürütülmez.


Bir içerik komut dosyasında bulunan sayfa değişikliklerini algılamaya yönelik genel JS yöntemleri .

  • DOM değişikliklerini tam anlamıyla algılamak için MutationObserver ( docs ):

  • Bir DOM etkinliği göndererek içerik değişikliğine işaret eden siteler için olay dinleyicisi :

  • DOM'un setInterval yoluyla periyodik kontrolü :
    Açıkçası bu, yalnızca kimliği / seçicisi tarafından tanımlanan belirli bir öğenin görünmesini beklediğiniz durumlarda çalışır ve bir tür parmak izi icat etmedikçe, evrensel olarak yeni eklenen içeriği tespit etmenize izin vermez mevcut içerik.

  • Gizleme Tarih APIenjekte DOM komut :

    document.head.appendChild(document.createElement('script')).text = '(' +
        function() {
            // injected DOM script is not a content script anymore, 
            // it can modify objects and functions of the page
            var _pushState = history.pushState;
            history.pushState = function(state, title, url) {
                _pushState.call(this, state, title, url);
                window.dispatchEvent(new CustomEvent('state-changed', {detail: state}));
            };
            // repeat the above for replaceState too
        } + ')(); this.remove();'; // remove the DOM script element
    
    // And here content script listens to our DOM script custom events
    window.addEventListener('state-changed', function(e) {
        console.log('History state changed', e.detail, location.hash);
        doSomething();
    });
  • Dinleme hashchange , popstate olaylar:

    window.addEventListener('hashchange', function(e) {
        console.log('URL hash changed', e);
        doSomething();
    });
    window.addEventListener('popstate', function(e) {
        console.log('State changed', e);
        doSomething();
    });



Uzantılara özgü: bir arka plan / etkinlik sayfasındaki URL değişikliklerini algılar .

Gezinme ile çalışmak için gelişmiş API vardır: webNavigation , webRequest , ancak içerik komut dosyasına mesaj gönderen basit chrome.tabs.onUpdated olay dinleyicisini kullanacağız :

  • manifest.json:
    declare background / event page içerik
    bildirimi betiği izin
    ekle ."tabs"

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

29

Div'i nasıl değiştirdiğinize bağlı olarak başka bir yaklaşım. Bir div'in içeriğini html () yöntemiyle değiştirmek için JQuery kullanıyorsanız, bu yöntemi genişletebilir ve html'yi div'a her yerleştirdiğinizde bir kayıt işlevini çağırabilirsiniz.

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

Biz sadece html () çağrılarını keseriz, bununla bir kayıt işlevi çağırırız, bu bağlamda yeni içerik elde eden hedef öğeyi ifade eder, daha sonra çağrıyı orijinal jquery.html () işlevine aktarırız. Orijinal html () yönteminin sonuçlarını döndürmeyi unutmayın, çünkü JQuery bunu yöntem zincirlemesi için bekler.

Yazdırma metodu ve uzatma hakkında daha fazla bilgi için check out http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm nerede olduğu Kapatma işlevini kopyaladım. Ayrıca JQuery'nin sitesindeki eklentiler eğitimine göz atın.


7

MutationObserverAPI tarafından sağlanan "ham" araçlara ek olarak, DOM mutasyonlarıyla çalışmak için "kolaylık" kitaplıkları da vardır.

Şunu düşünün: MutationObserver, alt ağaçlar açısından her DOM değişikliğini temsil eder. Örneğin, belirli bir öğenin yerleştirilmesini bekliyorsanız, öğelerinin derinliklerinde olabilir mutations.mutation[i].addedNodes[j].

Başka bir sorun, kendi kodunuz mutasyonlara tepki olarak DOM'u değiştirdiğinde - genellikle filtrelemek istediğinizdir.

Bu tür sorunları çözen iyi bir kolaylık kütüphanesi mutation-summary(sorumluluk reddi: Yazar değilim, sadece memnun bir kullanıcıyım), ilgilendiğiniz şeyleri sorgulamanızı ve tam olarak bunu almanızı sağlar.

Dokümanlardan temel kullanım örneği:

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