Die elegante Art, auf DOM-Änderungen zu achten

Lesezeit: 4 Minuten

Benutzer-Avatar
Ivo

Ich muss auf eine Attributänderung bei einem der untergeordneten Elemente eines bestimmten DOM-Elements achten. Bisher habe ich verwendet Mutationsereignisse.

Das Problem war – sie waren fehlerhaft: zB unter Chromium, DOMAttrModified wurde aber nicht gefeuert DOMSubtreeModified war. Das Problem war einfach zu lösen: Denn laut Spezifikation DOMSubtreeModified gefeuert wird, wenn eines der anderen Ereignisse gefeuert wird, also habe ich gerade zugehört DOMSubtreeModified.

Wie auch immer, Chromium hat in den letzten Versionen aufgehört, irgendetwas zu feuern, wenn ein Attribut geändert wurde.

Das neue Mutation Observer-APIfunktioniert aber einwandfrei.

Bis jetzt muss ich nur bei JEDER Änderung des Unterbaums eines bestimmten Elements einen Rückruf auslösen – einfach weil sich nichts anderes ändern soll – also habe ich mein Problem gelöst, indem ich einfach Mutationsereignisse und Mutationsbeobachter (falls verfügbar) in demselben verwendet habe Stück Code.

Jetzt muss ich jedoch die Ereignisse stärker filtern (z. B. auf neuen Knoten, auf entfernten Knoten) – so ist es da eine Bibliothek, möglicherweise ein jQuery-Plug-indas würde mir erlauben, elegant zu verwenden beide dieser APIs – MutationObserver falls verfügbar und Mutationsereignisse als Fallback, mit der Möglichkeit, nach bestimmten Ereignistypen zu filtern (z. B. Element hinzugefügt, Attribut geändert).

Z.B

$("#test").watch({onNewElement: 1}, function(newElement){})
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {})

Oder ohne jQuery

watchChanges("#test", {onNewElement: 1}, function(newElement){})
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){})

  • Einige Suchen haben dies gefunden, aber es unterstützt nur die neue API: code.google.com/p/mutation-summary. Ich habe auch Folgendes gefunden, was eine einfache Version dessen zu sein scheint, wonach Sie fragen: stackoverflow.com/questions/10868104/…

    – dreißig Punkte

    15. Juli 2012 um 11:56 Uhr

  • Ich habe auch Mutationszusammenfassung gefunden, aber es unterstützt keine Mutationsereignisse als Fallback. Die erste Antwort des von Ihnen geposteten Threads ist im Grunde das, was ich in meinem Code mache, um Attributänderungen zu beobachten. Nach dem gleichen Prinzip kann eine Bibliothek erstellt werden, die es ermöglicht, nach bestimmten DOM-Ereignissen zu suchen, indem sowohl Mutationsbeobachter als auch (als Fallback) Ereignisse verwendet werden. Das ist, was ich brauche.

    – Ivo

    15. Juli 2012 um 12:00 Uhr


  • +1: Ich grabe wirklich nach Best-Practice-Fragen.

    – Jezen Thomas

    21. Juli 2012 um 23:50 Uhr

Würde das funktionieren?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){
    if(!timeout)
        timeout = 10;
    return this.each(function(){
        var el      = $(this),
            func    = function(){ __check.call(this, el) },
            data    = { props:  props.split(","),
                        func:   callback,
                        vals:   [] };
        $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
        el.data(data);
        if (typeof (this.onpropertychange) == "object"){
            el.bind("propertychange", callback);
        } else if ($.browser.mozilla){
            el.bind("DOMAttrModified", callback);
        } else {
            setInterval(func, timeout);
        }
    });
    function __check(el) {
        var data    = el.data(),
            changed = false,
            temp    = "";
        for(var i=0;i < data.props.length; i++) {
            temp = el.css(data.props[i]);
            if(data.vals[i] != temp){
                data.vals[i] = temp;
                changed = true;
                break;
            }
        }
        if(changed && data.func) {
            data.func.call(el, data);
        }
    }
}

  • Ich habe es gesehen, aber es ist nur für Attribute. Außerdem greift es auf setInterval zurück, selbst wenn der Browser DOMAttrModified unterstützt.

    – Ivo

    21. Juli 2012 um 23:53 Uhr

  • @Ivo stimmt. Hier ist jedoch ein Gedanke – hast du die Kontrolle über all diese Veränderungen, die mit dem Dom geschehen? Haben Sie darüber nachgedacht, die jquery-Manipulationsmethoden zu überschreiben, um ein change/append/remove-Ereignis auszulösen (aber das setzt voraus, dass alle Änderungen über jquery erfolgen). Ich weiß, das ist eine Menge Arbeit und nicht genau das, wonach Sie suchen, aber die Arbeit wird erledigt.

    – Kaffeebissen

    22. Juli 2012 um 0:54 Uhr

  • Ich habe die Arbeit schon vor langer Zeit erledigt – ich verwende sowohl Mutationsereignisse als auch Beobachter, um Attribute zu überwachen, und ich verwende nur die Ereignisse, um nach neu hinzugefügten Dingen im DOM zu suchen – und ich habe nicht ganz die Kontrolle, seit ich beobachte für Änderungen, die über den contenteditable/WYSIHTML5-Editor vorgenommen wurden. Aber es funktioniert alles für die Browser, die ich unterstützen möchte. Dies ist eher eine “Best Approach”-Frage. Und Affen-Patching von jQuery scheint eine schlechte Idee zu sein. Das Monkey-Patching der DOM-API ist möglicherweise angemessener, aber ich bin mir immer noch nicht sicher.

    – Ivo

    22. Juli 2012 um 10:43 Uhr

Benutzer-Avatar
FloSelbst

Für eine effiziente DOM-Überwachung mit jQuery können Sie einen Blick auf die jQuery-Verhaltens-Plugin (Haftungsausschluss: Ich bin der Autor), der eine optimierte Version von verwendet Live-Abfrage. Ich benutze es seit 3 ​​Jahren in mehreren Produkten ohne Probleme.

Bearbeiten: Das Abhören von Attributänderungen würde wie folgt funktionieren:

$.behavior({
    'div:first': {
        'changeAttr': function (event, data) {
            console.log('Attribute "' +  data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"');
        }
    }
});

$('div:first').attr('foo', 'bar');

1187630cookie-checkDie elegante Art, auf DOM-Änderungen zu achten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy