javascript - Vanilla JS 事件委托(delegate) - 处理目标元素的子元素

标签 javascript dom publish-subscribe event-delegation

我正在尝试在 vanilla JS 中进行事件委托(delegate)。我在这样的容器内有一个按钮

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

并关注David Walsh's nice instructions我将事件处理程序添加到按钮的祖先,如下所示:

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

其中 this.container 是 #quiz 元素。这在一半的情况下有效,但其余时间单击事件的目标是按钮内的跨度之一,因此不会调用我的事件处理程序。处理这种情况的最佳方法是什么?

最佳答案

较新的浏览器

较新的浏览器支持.matches :

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

您可以通过以下方式获取无前缀版本

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

然后对更多浏览器使用.apply(仍然是IE9+)。

旧版浏览器

假设您必须支持旧版浏览器,您可以遍历 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
}

但是,这将爬升整个 dom,并且您想在委托(delegate)目标处停止:

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
}

这将使您的代码:

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

关于javascript - Vanilla JS 事件委托(delegate) - 处理目标元素的子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24117369/

相关文章:

java - 向 child 添加appendChild时遇到问题

java - 如何将 Spring Integration Consumer 配置为事件驱动?

javascript - Chrome 扩展程序在一段时间后停止工作。响应未定义

javascript - Angularjs可选择突出显示的行

javascript 文件未加载

python - Selenium 下载整个 html

javascript - 想要在下拉列表更改事件时在 session 变量中设置值

javascript - 在渲染之前,如何使用 jQuery 找到元素的预期渲染宽度?

PHP在post请求中读取xml

javascript - 使用发布复合进行共享连接: pull out user's posts + comments