469 Stimmen

Gibt es einen JavaScript / jQuery DOM-Änderungshörer?

Im Grunde möchte ich, dass ein Skript ausgeführt wird, wenn sich der Inhalt eines DIV ändert. Da die Skripts getrennt sind (Inhaltsskript in der Chrome-Erweiterung und Websitenskript), brauche ich eine einfache Möglichkeit, Änderungen im DOM-Zustand zu beobachten. Ich könnte eine Überwachung einrichten, aber das scheint schlampig zu sein.

1 Stimmen

Beantwortet das deine Frage? Änderungen im DOM erkennen

563voto

apsillers Punkte 108008

DOM3-Mutationsereignisse waren lange Zeit die beste verfügbare Lösung, wurden jedoch aus Leistungsgründen abgelehnt. DOM4 Mutation Observers sind der Ersatz für die veralteten DOM3-Mutationsereignisse. Sie sind derzeit in modernen Browsern implementiert als MutationObserver (oder als vendor-prefix WebKitMutationObserver in alten Versionen von Chrome):

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {
    // wird ausgelöst, wenn eine Mutation auftritt
    console.log(mutations, observer);
    // ...
});

// definieren, welches Element vom Observer überwacht werden soll
// und welche Arten von Mutationen den Rückruf auslösen
observer.observe(document, {
  subtree: true,
  attributes: true
  //...
});

Dieses Beispiel hört auf DOM-Änderungen an document und dessen gesamtem Unterbaum und wird bei Änderungen an Elementattributen sowie strukturellen Änderungen ausgelöst. Der Entwurfsspezifikation enthält eine vollständige Liste gültiger Mutationslistener-Eigenschaften:

childList

  • Wird auf true gesetzt, wenn Mutationen an den Kindern des Ziels beobachtet werden sollen.

attributes

  • Wird auf true gesetzt, wenn Mutationen an den Attributen des Ziels beobachtet werden sollen.

characterData

  • Wird auf true gesetzt, wenn Mutationen an den Daten des Ziels beobachtet werden sollen.

subtree

  • Wird auf true gesetzt, wenn Mutationen nicht nur am Ziel, sondern auch an den Nachkommen des Ziels beobachtet werden sollen.

attributeOldValue

  • Wird auf true gesetzt, wenn attributes auf true gesetzt ist und der Attributwert des Ziels vor der Mutation aufgezeichnet werden muss.

characterDataOldValue

  • Wird auf true gesetzt, wenn characterData auf true gesetzt ist und die Daten des Ziels vor der Mutation aufgezeichnet werden müssen.

attributeFilter

  • Wird auf eine Liste von Attributlokalnamen (ohne Namensraum) gesetzt, wenn nicht alle Attributmutationen beobachtet werden müssen.

(Diese Liste ist auf dem Stand von April 2014; Sie können die Spezifikation auf Änderungen überprüfen.)

3 Stimmen

@AshrafBashir Ich sehe das Beispiel gut funktionieren in Firefox 19.0.2: Ich sehe ([{}]) im Konsolenprotokoll, was den erwarteten MutationRecord zeigt, wenn ich darauf klicke. Bitte überprüfen Sie noch einmal, da es sich möglicherweise um einen vorübergehenden technischen Fehler in JSFiddle handelt. Ich habe es noch nicht in IE getestet, da ich kein IE 10 habe, der derzeit die einzige Version ist, die Mutationsereignisse unterstützt.

1 Stimmen

Ich habe gerade eine Antwort gepostet, die in IE10+ funktioniert und weitgehend mit allem anderen kompatibel ist.

1 Stimmen

Die Spezifikation scheint nicht mehr über eine grüne Box zu verfügen, die die Mutationsbeobachteroptionen auflistet. Sie listet die Optionen im Abschnitt 5.3.1 auf und beschreibt sie etwas weiter unten.

225voto

Anurag Punkte 136648

Bearbeiten

Diese Antwort ist jetzt veraltet. Siehe die Antwort von apsillers.

Da es sich um eine Chrome-Erweiterung handelt, sollten Sie besser das Standard-DOM-Ereignis verwenden - DOMSubtreeModified. Sehen Sie die Unterstützung für dieses Ereignis in verschiedenen Browsern. Es wird in Chrome seit 1.0 unterstützt.

$("#someDiv").bind("DOMSubtreeModified", function() {
    alert("Baum geändert");
});

Sehen Sie ein funktionierendes Beispiel hier.

0 Stimmen

Ich habe festgestellt, dass dieses Ereignis auch nach bestimmten Selektoren ausgelöst werden kann. Ich untersuche das gerade.

9 Stimmen

w3.org/TR/DOM-Level-3-Events/#event-type-DOMSubtreeModified sagt, dass dieses Ereignis veraltet ist. Was würden wir stattdessen verwenden?

2 Stimmen

@Maslow - Es gibt nicht! stackoverflow.com/questions/6659662/…

91voto

wOxxOm Punkte 52257

Viele Websites verwenden AJAX/XHR/fetch, um Inhalte dynamisch hinzuzufügen, anzuzeigen und zu ändern, und die window.history API anstelle einer Navigation innerhalb der Website, sodass die aktuelle URL programmgesteuert geändert wird. Solche Websites werden als SPA bezeichnet, kurz für Single Page Application.


Gewöhnliche JS-Methoden zur Erkennung von Seitenänderungen

  • MutationObserver (Dokumentation) zum Buchstäblich Erkennen von DOM-Änderungen.

    Informationen/Beispiele:

  • Eventlistener für Websites, die eine Änderung des Inhalts durch Senden eines DOM-Ereignisses signalisieren:

  • Periodisches Überprüfen des DOM über setInterval:
    Offensichtlich funktioniert dies nur in Fällen, in denen Sie auf das Erscheinen eines bestimmten Elements warten, das durch seine ID/Auswahlkriterien identifiziert wird, und es wird Ihnen nicht universell ermöglichen, neu hinzugefügten dynamischen Inhalt zu erkennen, es sei denn, Sie erfinden eine Art von Fingerabdruck für die vorhandenen Inhalte.

  • Verstecken des History API:

    let _pushState = History.prototype.pushState;
    History.prototype.pushState = function (state, title, url) {
      _pushState.call(this, state, title, url);
      console.log('URL geändert', url)
    };
  • Hören auf hashchange-, popstate-Ereignisse:

    window.addEventListener('hashchange', e => {
      console.log('URL-Hash geändert', e);
      etwasTun();
    });
    window.addEventListener('popstate', e => {
      console.log('Zustand geändert', e);
      etwasTun();
    });

P.S. Alle diese Methoden können in einem WebExtension-Inhaltsskript verwendet werden. Das liegt daran, dass wir es mit einem Fall zu tun haben, in dem die URL über history.pushState oder replaceState geändert wurde, sodass die Seite selbst in der gleichen Inhalts-Skript-Umgebung bleibt.

29voto

Zac Imboden Punkte 751

Ein weiterer Ansatz hängt davon ab, wie Sie das Div ändern. Wenn Sie JQuery verwenden, um den Inhalt eines Divs mit seiner html() Methode zu ändern, können Sie diese Methode erweitern und jedes Mal, wenn Sie html in ein Div setzen, eine Registrierungsfunktion aufrufen.

(function( $, oldHtmlMethod ){
    // Überschreiben Sie die Kern-HTML-Methode im jQuery-Objekt.
    $.fn.html = function(){
        // Führen Sie die ursprüngliche HTML-Methode unter Verwendung der
        // erweiterten Argumentensammlung aus.

        var results = oldHtmlMethod.apply( this, arguments );
        com.invisibility.elements.findAndRegisterElements(this);
        return results;

    };
})( jQuery, jQuery.fn.html );

Wir unterbrechen einfach die Aufrufe von html(), rufen eine Registrierungsfunktion mit diesem auf, was im Kontext auf das Ziellement verweist, das neuen Inhalt erhält, und leiten den Aufruf an die ursprüngliche jquery.html() Funktion weiter. Denken Sie daran, die Ergebnisse der ursprünglichen html() Methode zurückzugeben, weil JQuery dies für die Methodenverkettung erwartet.

Weitere Informationen zur Methodenüberschreibung und -erweiterung finden Sie unter http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm, wo ich die Closure-Funktion abgekupfert habe. Schauen Sie sich auch das Plugin-Tutorial auf der JQuery-Website an.

9voto

Xan Punkte 71077

Zusätzlich zu den "rohen" Tools, die von der MutationObserver-API bereitgestellt werden, gibt es "Komfort"-Bibliotheken, um mit DOM-Mutationen zu arbeiten.

Betrachten Sie: MutationObserver stellt jede DOM-Änderung in Form von Teilbäumen dar. Wenn Sie beispielsweise auf ein bestimmtes Element warten, das eingefügt werden soll, befindet es sich möglicherweise tief in den Kindern von mutations.mutation[i].addedNodes[j].

Ein weiteres Problem besteht darin, dass Ihr eigener Code, als Reaktion auf Mutationen, das DOM ändert - Sie möchten dies oft filtern.

Eine gute Komfort-Bibliothek, die solche Probleme löst, ist mutation-summary (Haftungsausschluss: Ich bin nicht der Autor, sondern ein zufriedener Benutzer), mit der Sie Abfragen zu dem angeben können, was Sie interessiert, und genau das erhalten.

Ein grundlegendes Beispiel aus der Dokumentation:

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

0 Stimmen

Ich habe arrive.js als sehr gute MutationObserver-Komfortbibliothek gefunden. Ich stimme Ihrem Haftungsausschluss zu, bin nicht der Autor, aber ein sehr zufriedener Benutzer.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X