简体   繁体   English

Javascript 相当于 $.on

[英]Javascript equivalent to $.on

As somebody who ( unfortunately ) learned more of jQuery than raw javascript I am just now taking the time to replace all of my code with raw javascript .作为一个(不幸的是)比原始javascript学到更多jQuery的人,我现在正花时间用原始javascript替换我的所有代码。 No, it's not needed, but it's an easier way for me to learn.不,不需要,但这对我来说是一种更容易学习的方法。 A problem I am facing is converting all of my $(document).on with raw javascript .我面临的一个问题是将我所有的$(document).on为原始javascript My website is a "single-page application" and most of my actual HTML is in different files which are called via Ajax requests.我的网站是一个“单页应用程序”,我的大部分实际HTML都在通过Ajax请求调用的不同文件中。 So, my question is, how would I look for an event fired from dynamically loaded content?所以,我的问题是,我将如何查找从动态加载的内容触发的event I am assuming I would have to add an onclick event to them, but how is it that jQuery does it without needing an onclick event ?我假设我必须向它们添加一个onclick事件,但是jQuery是如何在不需要onclick event的情况下完成的?

Binding handlers in native API is done using addEventListener() . 本机API中的绑定处理程序是使用addEventListener()

To emulate jQuery's event delegation, you could fairly easily create a system that uses the .matches() method to test the selector you give. 要模拟jQuery的事件委托,您可以相当轻松地创建一个使用.matches()方法来测试您提供的选择器的系统。

function delegate(el, evt, sel, handler) {
    el.addEventListener(evt, function(event) {
        var t = event.target;
        while (t && t !== this) {
            if (t.matches(sel)) {
                handler.call(t, event);
            }
            t = t.parentNode;
        }
    });
}

There are probably some tweaks to be made, but basically it's a function that takes the element to bind to, like document , the event type, a selector and the handler. 可能会进行一些调整,但基本上它是一个函数,它将元素绑定到document ,事件类型,选择器和处理程序。

It starts on the e.target and traverses up the parents until it gets to the bound element. 它从e.target开始并遍历父e.target ,直到它到达绑定元素。 Each time, it checks to see if the current element matches the selector, and if so, it invokes the handler. 每次,它检查当前元素是否与选择器匹配,如果是,则调用处理程序。

So you'd call it like this: 所以你会这样称呼它:

delegate(document, "click", ".some_elem", function(event) {
    this.style.border = "2px dashed orange";
});

Here's a live demo that also adds dynamic elements to show that new elements are picked up as well. 这是一个现场演示,它还添加了动态元素,以显示新元素也被拾取。

 function delegate(el, evt, sel, handler) { el.addEventListener(evt, function(event) { var t = event.target; while (t && t !== this) { if (t.matches(sel)) { handler.call(t, event); } t = t.parentNode; } }); } delegate(document, "click", ".some_elem", function(event) { this.parentNode.appendChild(this.cloneNode(true)); this.style.border = "2px dashed orange"; }); 
 <div> <p class="some_elem"> <span> CLICK ME </span> </p> </div> 


Here's a shim to add a bit more support for .matches() . 这是一个垫片,可以为.matches()添加更多支持。

if (!Element.prototype.matches) {
  Element.prototype.matches = 
    Element.prototype.matchesSelector || 
    Element.prototype.webkitMatchesSelector ||
    Element.prototype.mozMatchesSelector ||
    Element.prototype.msMatchesSelector || 
    Element.prototype.oMatchesSelector || 
    function(s) {
        var matches = (this.document || this.ownerDocument).querySelectorAll(s),
            i = matches.length;
        while (--i >= 0 && matches.item(i) !== this) {}
        return i > -1;            
    };
}

Here is a javascript equivalent to on() 这是一个相当于 on()的javascript

jQuery jQuery的

$(document).on('click', '#my-id', callback);

function callback(){
   ...handler code here
}

Javascript 使用Javascript

document.addEventListener('click', function(event) {
    if (event.target.id == 'my-id') {
      callback();
    }
});
function callback(){
   ...handler code here
}

With this approach, the idea is to make use of event.target . 使用这种方法,想法是使用event.target Of course, as the selector changes, your code will have to get more involved 当然,随着选择器的改变,你的代码必须更多地参与其中

In modern browsers, you can use Element.closest() to simplify replication of jQuery's .on() method as well as ensure that you capture event bubbling from children of the targeted element (a nuance that some other implementations overlook). 在现代浏览器中,您可以使用Element.closest()来简化jQuery的.on()方法的复制,并确保捕获来自目标元素的子元素的事件冒泡(一些其他实现忽略的细微差别)。 Older browsers, including IE, would require a polyfill for this to work. 较旧的浏览器(包括IE)需要使用polyfill才能工作。

 const on = (element, event, selector, handler) => { element.addEventListener(event, e => { if (e.target.closest(selector)) { handler(e); } }); } on(document, 'click', '#test', e => { console.log('click'); }); 
 <button id="test"> Clickable <i>Also Clickable</i> </button> 

Another approach for modern browsers would be something like this: 现代浏览器的另一种方法是这样的:

 const on = (selector, event, handler, element=document) => { element.addEventListener(event, (e) => { if(e.target.matches(selector)) handler(e); }); }; // click will work for each selector on('[type="button"], .test, #test','click', e => { alert(e.target.innerHTML); }); // click event will work for nested .test3 element only on('.test3','click', e => { alert(e.target.innerHTML); },document.querySelector('.test2')); 
 <div id="test"> test </div> <div class="test"> test 1 </div> <div class="test"> test 2 </div> <button type="button"> go </button> <div class="test3"> test 3 outer </div> <div class="test2"> <div class="test3"> test 3 inner </div> test 2 </div> 

I would offer a very small improvement over the fantastic accepted answer :我会提供一个非常小的改进,比出色的公认答案

function add_event(el, name, callback, selector) {
    if (selector === undefined) {
        el.addEventListener(name, callback);
    }
    else {
        el.addEventListener(name, function(event) {
            var t = event.target;
            while (t && t !== this) {
                if (t.matches(selector)) {
                    callback.call(t, event);
                }
                t = t.parentNode;
            }
        });
    }
}

By switching the last 2 parameters around, you can recover the default addEventListener behavior when you leave out the selector.通过切换最后 2 个参数,您可以在省略选择器时恢复默认的 addEventListener 行为。

I want to add and suggest a simple jQuery like on method: It's similar to @benvc answer with an improvement which is binding the handler to this pointing to the attached element.我想添加并建议一个简单的 jQuery 方法:它类似于@benvc 的回答,但有一个改进,即将处理程序绑定到指向附加元素的this The solution uses Element.closest which is widely supported.该解决方案使用广泛支持的Element.closest If you want to support older browsers you can add a polyfill如果你想支持旧的浏览器,你可以添加一个polyfill

//The on() function:
const on = (ele, type, selector, handler) => {
    ele.addEventListener(type, (event) => {
        let el = event.target.closest(selector);
        if (el) handler.call(el, event); //The element is bind to this
    });
};


//Example:
on(document, 'click', '.any-selector', function(event) {
     console.log(this, event.target);
     // this         -> The .any-selector element.
     // event.target -> The firing element a descendent of any-selector
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM