33 Stimmen

Vanilla JS Event Delegation - Umgang mit Kinderelementen des Ziellements

Ich versuche, Event-Delegation in Vanilla JS zu machen. Ich habe einen Button in einem Container wie diesem:

        Go again

Und gemäß David Walshs Anweisungen füge ich einen Event-Handler zu einem Vorfahren des Buttons hinzu, wie folgt:

this.container.addEventListener('click', function(e){
    if (e.target && e.target.id == 'game-again') {
        e.stopPropagation();
        self.publish('primo:evento');
    }
});

Wo this.container das Element #quiz ist. Dies funktioniert die Hälfte der Zeit, aber die restliche Zeit ist das Ziel des Klick-Ereignisses eines der Spans innerhalb des Buttons, sodass mein Event-Handler nicht aufgerufen wird. Wie kann man am besten mit dieser Situation umgehen?

46voto

Benjamin Gruenbaum Punkte 259076

Neuere Browser

Neuere Browser unterstützen .matches:

this.container.addEventListener('click', function(e){
    if (e.target.matches('#game-again,#game-again *')) {
        e.stopPropagation();
        self.publish('primo:evento');
    }
});

Sie können die Version ohne Präfix mit erhalten

var matches = document.body.matchesSelector || document.body.webkitMatchesSelector || document.body.mozMatchesSelector || document.body.msMatchesSelector || document.body.webkitMatchesSelector

Und dann .apply für weitere Browser verwenden (immer noch IE9+).

Ältere Browser

Angenommen, Sie müssen ältere Browser unterstützen, können Sie den DOM durchlaufen:

function hasInParents(el,id){
    if(el.id === id) return true; // das Element
    if(el.parentNode) return hasInParents(el.parentNode,id); // ein Eltern-Element
    return false; // nicht das Element oder seine Eltern
}

Allerdings wird dies den gesamten DOM durchlaufen und Sie möchten beim Delegationsziel aufhören:

function hasInParentsUntil(el,id,limit){
    if(el.id === id) return true; // das Element
    if(el === limit) return false;
    if(element.parentNode) return hasInParents(el.parentNode,id); // ein Eltern-Element
    return false; // nicht das Element oder seine Eltern
}

Was Ihren Code wie folgt aussehen lassen würde:

this.container.addEventListener('click', function(e){
    if (hasInParentsUntil(e.target,'game-again',container)) { // container sollte 
        e.stopPropagation();                                  // für dieses verfügbar sein
        self.publish('primo:evento');
    }
});

11voto

C.OG Punkte 6414

Alternative Lösung:

MDN: Zeigereignisse

Fügen Sie allen verschachtelten Kindelementen eine Klasse hinzu (.pointer-none)

.pointer-none {
  pointer-events: none;
}

Ihr Markup sieht dann wie folgt aus

        Nochmal

Bei Einstellung des Zeigers auf "none" wird das Klickevent auf diese Elemente nicht ausgelöst.

https://css-tricks.com/slightly-careful-sub-elements-clickable-things/

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