在纯javascript中使用选择器模拟jQuery"on"

Luc*_*one 13 javascript javascript-events

我会在纯javascript中模拟jQuery .on( events , selector , data) 方法的主要功能.

例如

$(document).on('click','.button',function() {
   console.log("jquery onclick"); 
});
Run Code Online (Sandbox Code Playgroud)

我认为这样就足够了

document.addEventListener('click',function(e) {
    if(e.target.className == 'button2') {
         console.log("It works");   
    }
});
Run Code Online (Sandbox Code Playgroud)

但是,当我有这个HTML结构时:

<button class="button2">Hello <span>World</span></button>
Run Code Online (Sandbox Code Playgroud)

当被触发的单击事件我的脚本不工作的span元素,因为e.targetspan.(我忽略了这个问题,具有多个类的元素的复杂性,以及交叉浏览器的兼容性)

jQuery源代码不易阅读,我不明白它是如何工作的(因为jQuery中的第一段代码与我的html结构一起工作).

我需要这种方法,因为我的html是动态的,并且多次创建,删除和重新创建具有此类的按钮.我不希望每次都添加监听器.

如果可能的话,我会避免包含jquery库.

那么,我可以这样做吗?

这里是用于测试的jsFiddle.

Nie*_*sol 10

这实际上非常简单.你走在正确的轨道上,但它并不存在.

这是我使用的功能:

window.addEvent = function(elem,type,callback) {
    var evt = function(e) {
        e = e || window.event;
        return callback.call(elem,e);
    }, cb = function(e) {return evt(e);};
    if( elem.addEventListener) {
        elem.addEventListener(type,cb,false);
    }
    else if( elem.attachEvent) {
        elem.attachEvent("on"+type,cb);
    }
    return elem;
};
window.findParent = function(child,filter,root) {
    do {
        if( filter(child)) return child;
        if( root && child == root) return false;
    } while(child = child.parentNode);
    return false;
};
window.hasClass = function(elem,cls) {
    if( !('className' in elem)) return;
    return !!elem.className.match(new RegExp("\\b"+cls+"\\b"));
};
Run Code Online (Sandbox Code Playgroud)

window.findParent是整个事情的核心,你可以看到我告诉你如何附加你想要的on听众:

window.addEvent(document.body,"click",function(e) {
    var s = window.findParent(e.srcElement || e.target,function(elm) {
        return window.hasClass(elm,"button");
    },this);
    if( s) {
        console.log("It works!");
    }
});
Run Code Online (Sandbox Code Playgroud)


mik*_*ana 10

2017年更新:目前的DOM标准closest意味着现在更加容易.

const addEventForChild = function(parent, eventName, childSelector, cb){      
  parent.addEventListener(eventName, function(event){
    const clickedElement = event.target,
    matchingChild = clickedElement.closest(childSelector)
    if (matchingChild) cb(matchingChild)
  })
};
Run Code Online (Sandbox Code Playgroud)

要使用它:

addEventForChild(parent, 'click', '.child', function(childElement){
  console.log('Woo click!', childElement)
})
Run Code Online (Sandbox Code Playgroud)

这是一个jsfiddle

  • @AndrewNewby不确定为什么你在2018年支持IE,但你可以填充`element.closest`并使用它直到你放弃IE. (3认同)