Vanilla JS event delegation - dealing with child elements of the target element

前端 未结 2 1694
挽巷
挽巷 2020-11-28 09:35

I\'m trying to do event delegation in vanilla JS. I have a button inside a container like this

相关标签:
2条回答
  • 2020-11-28 09:50

    Newer browsers

    Newer browsers support .matches:

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

    You can get the unprefixed version with

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

    And then use .apply for more browsers (Still IE9+).

    Older browsers

    Assuming you have to support older browsers, you can walk up the DOM:

    function hasInParents(el,id){
        if(el.id === id) return true; // the element
        if(el.parentNode) return hasInParents(el.parentNode,id); // a parent
        return false; // not the element nor its parents
    }
    

    However, this will climb the whole dom, and you want to stop at the delegation target:

    function hasInParentsUntil(el,id,limit){
        if(el.id === id) return true; // the element
        if(el === limit) return false;
        if(element.parentNode) return hasInParents(el.parentNode,id); // a parent
        return false; // not the element nor its parents
    }
    

    Which, would make your code:

    this.container.addEventListener('click', function(e){
        if (hasInParentsUntil(e.target,'game-again',container)) { // container should be 
            e.stopPropagation();                                  // available for this
            self.publish('primo:evento');
        }
    });
    
    0 讨论(0)
  • 2020-11-28 10:11

    Alternate Solution:

    MDN: Pointer events

    Add a class to all nested child elements (.pointer-none)

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

    Your mark-up becomes

    <div id="quiz">
        <button id="game-again" class="game-again">
            <span class="icon-spinner icon pointer-none"></span>
            <span class="pointer-none">Go again</span>
        </button>
    </div>
    

    With the pointer set to none, the click event wouldn't fire on those elements.

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

    0 讨论(0)
提交回复
热议问题