Ereignisauslöser bei einem Klassenwechsel

Lesezeit: 5 Minuten

Benutzer-Avatar
Patrick Jon

Ich möchte, dass meine Veranstaltung Ausgelöst wenn ein div-Tag mit a Abzug Klasse wird gewechselt.

Ich habe keine Ahnung, wie man es dazu bringt, auf das Hinzufügen von Ereignissen der Klasse zu hören.

<div id="test">test</div>

<script type="text/javascript">
    document.getElementById.setAttribute("class", "trigger");

    function workOnClassAdd() {
       alert("I'm triggered");
    }
</script>

  • Wissen Sie sicher, dass die Klasse aktualisiert wird mit .setAttribute() oder sprechen Sie in willkürlicheren Begriffen (dh Sie möchten, dass der Ereignishandler ausgelöst wird, selbst wenn ein Benutzer die Klasse über Firebug ändert)?

    – jaredhoyt

    16. Mai 2012 um 4:42 Uhr


  • FYI stackoverflow.com/questions/1950038/…

    – Dasarp

    16. Mai 2012 um 4:50 Uhr

Benutzer-Avatar
TechWeisheit

Die Zukunft ist da, und Sie können die nutzen Mutationsbeobachter Schnittstelle, um nach a Ausschau zu halten Spezifisch Klassenwechsel.

let targetNode = document.getElementById('test')

function workOnClassAdd() {
    alert("I'm triggered when the class is added")
}

function workOnClassRemoval() {
    alert("I'm triggered when the class is removed")
}

// watch for a specific class change
let classWatcher = new ClassWatcher(targetNode, 'trigger', workOnClassAdd, workOnClassRemoval)

// tests:
targetNode.classList.add('trigger') // triggers workOnClassAdd callback
targetNode.classList.add('trigger') // won't trigger (class is already exist)
targetNode.classList.add('another-class') // won't trigger (class is not watched)
targetNode.classList.remove('trigger') // triggers workOnClassRemoval callback
targetNode.classList.remove('trigger') // won't trigger (class was already removed)
targetNode.setAttribute('disabled', true) // won't trigger (the class is unchanged)

Ich habe gewickelt Mutationsbeobachter mit einer einfachen Klasse:

class ClassWatcher {

    constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
        this.targetNode = targetNode
        this.classToWatch = classToWatch
        this.classAddedCallback = classAddedCallback
        this.classRemovedCallback = classRemovedCallback
        this.observer = null
        this.lastClassState = targetNode.classList.contains(this.classToWatch)

        this.init()
    }

    init() {
        this.observer = new MutationObserver(this.mutationCallback)
        this.observe()
    }

    observe() {
        this.observer.observe(this.targetNode, { attributes: true })
    }

    disconnect() {
        this.observer.disconnect()
    }

    mutationCallback = mutationsList => {
        for(let mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                let currentClassState = mutation.target.classList.contains(this.classToWatch)
                if(this.lastClassState !== currentClassState) {
                    this.lastClassState = currentClassState
                    if(currentClassState) {
                        this.classAddedCallback()
                    }
                    else {
                        this.classRemovedCallback()
                    }
                }
            }
        }
    }
}

  • Sehr schönes Stück Code mit Beobachtermuster! Ich würde auch dringend vorschlagen, in mutationCallback … this.classAddedCallback() und this.classRemovedCallback() “this” in Parameter von Callback-Funktionen einzufügen. Also … this.classAddedCallback(this) und this.classRemovedCallback(this). Dadurch erhalten Sie einen einfachen Zugriff auf bestimmte ClassWatcher-Objekte in Callback-Funktionen und damit Zugriff auf den targetNode und andere Parameter, die nach dem Triggerereignis sehr nützlich zu bearbeiten sind!

    – R3qUi3M

    11. Februar um 17:43 Uhr

Nun, es gab Mutationsereignisse, aber sie waren veraltet und in Zukunft wird es Mutation Observers geben, aber sie werden noch lange nicht vollständig unterstützt. Was können Sie also in der Zwischenzeit tun?

Sie können einen Timer verwenden, um das Element zu überprüfen.

function addClassNameListener(elemId, callback) {
    var elem = document.getElementById(elemId);
    var lastClassName = elem.className;
    window.setInterval( function() {   
       var className = elem.className;
        if (className !== lastClassName) {
            callback();   
            lastClassName = className;
        }
    },10);
}

Laufendes Beispiel: jsFiddle

  • Wurde dafür kritisiert, dass Sie Ihre Antwort nicht perfekt referenziert haben … Wie auch immer, es kann sogar mit gemacht werden dieses Plugin einfach… Meine Antwort auf eine ähnliche Frage ist hier.. Hoffe es hilft jemandem

    – Bhavik

    4. Mai 2014 um 17:57 Uhr

  • Mutationsbeobachter sind heutzutage verfügbar, woooohoooo!

    – Ivan Š

    19. Juli 2016 um 12:33 Uhr

  • Yah, es scheint, dass Mutation Observers jetzt breite Unterstützung findet. developer.mozilla.org/en-US/docs/Web/API/MutationObserver

    – MVEntwickler1

    19. August 2020 um 12:48 Uhr

Benutzer-Avatar
Roko C. Buljan

Hier ist ein einfaches, grundlegendes Beispiel zum Auslösen von a Rückruf bei Änderung des Klassenattributs
MutationObserver-API

const attrObserver = new MutationObserver((mutations) => {
  mutations.forEach(mu => {
    if (mu.type !== "attributes" && mu.attributeName !== "class") return;
    console.log("class was modified!");
  });
});

const ELS_test = document.querySelectorAll(".test");
ELS_test.forEach(el => attrObserver.observe(el, {attributes: true}));


// Example of Buttons toggling several .test classNames
document.querySelectorAll(".btn").forEach(btn => {
  btn.addEventListener("click", () => ELS_test.forEach(el => el.classList.toggle(btn.dataset.class)));
});
.blue {background: blue;}
.gold {color: gold;}
<div class="test">TEST DIV</div>
<button class="btn" data-class="blue">BACKGROUND</button>
<button class="btn" data-class="gold">COLOR</button>

Kann das verwenden onClassChange Funktion zu sehen, wann immer classList eines Elements ändert

function onClassChange(element, callback) {
  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (
        mutation.type === 'attributes' &&
        mutation.attributeName === 'class'
      ) {
        callback(mutation.target);
      }
    });
  });
  observer.observe(element, { attributes: true });
  return observer.disconnect;
}

var itemToWatch = document.querySelector('#item-to-watch');
onClassChange(itemToWatch, (node) => {
  node.classList.contains('active')
    ? alert('class added')
    : alert('class removed');
  node.textContent="Item to watch. classList: " + node.className;
});

function addClass() {
  itemToWatch.classList.add('active');
}

function removeClass() {
  itemToWatch.classList.remove('active');
}
<div id="item-to-watch">Item to watch</div>
<button onclick="addClass();">Add Class</button>
<button onclick="removeClass();">Remove Class</button>

Benutzer-Avatar
JosefNewYork

Ich brauchte einen Listener für Klassenaktualisierungen für ein Projekt, also habe ich das auf die Beine gestellt. Ich habe es nicht verwendet, daher ist es nicht vollständig getestet, sollte aber in Browsern funktionieren, die Element.classList DOMTokenList unterstützen.

Bonus: ermöglicht zum Beispiel das „Verketten“ der 4 unterstützten Methoden el.classList.remove(“inactive”).remove(“disabled”).add(“active”)

function ClassListListener( el ) {
  const ecl = el.classList;
  ['add','remove','toggle','replace'].forEach(prop=>{
    el.classList['_'+prop] = ecl[prop]
    el.classList[prop] = function() {
      const args = Array.from(arguments)
      this['_'+prop].apply(this, args)
      el.dispatchEvent(new CustomEvent(
        'classlistupdate',
        { detail: { method: prop, args } }
      ))
      return this
    }
  })
  return el
}

Verwendung:


const el = document.body

ClassListListener(el).addEventListener('classlistupdate', e => {
    const args = e.detail.args.join(', ')
    console.log('el.classList.'+e.detail.method+'('+args+')')
}, false)

el.classList
  .add('test')
  .replace('test', 'tested')

  • Hallo, willkommen bei Stackoverflow, können Sie verwenden beschreibender Variablennamen?

    – Abilogos

    26. August 2021 um 16:19 Uhr

  • Bitte fügen Sie weitere Details hinzu, um Ihre Antwort zu erweitern, z. B. Arbeitscode oder Dokumentationszitate.

    – Gemeinschaft
    bot

    26. August 2021 um 16:19 Uhr

  • Hallo, willkommen bei Stackoverflow, können Sie verwenden beschreibender Variablennamen?

    – Abilogos

    26. August 2021 um 16:19 Uhr

  • Bitte fügen Sie weitere Details hinzu, um Ihre Antwort zu erweitern, z. B. Arbeitscode oder Dokumentationszitate.

    – Gemeinschaft
    bot

    26. August 2021 um 16:19 Uhr

1011440cookie-checkEreignisauslöser bei einem Klassenwechsel

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

Privacy policy