Javascript相当于$ .on

时间:2015-06-17 01:10:00

标签: javascript jquery

正如某人(不幸)了解了更多jQuery而非原始 javascript的人,我现在正在花时间更换我的所有原始javascript的代码。不,这不是必需的,但这对我来说是一种更容易学习的方式。我遇到的一个问题是将所有$(document).on转换为原始javascript。我的网站是一个“单页面应用程序”,我的大多数实际HTML都在不同的文件中,这些文件是通过Ajax请求调用的。所以,我的问题是,我如何寻找动态加载内容的event?我假设我必须向他们添加onclick个事件,但jQuery如何在不需要onclick event的情况下做到这一点?

5 个答案:

答案 0 :(得分:34)

本机API中的绑定处理程序是使用addEventListener()完成的。

要模拟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;
        }
    });
}

可能会进行一些调整,但基本上它是一个将元素绑定到的函数,如document,事件类型,选择器和处理程序。

它从e.target开始并遍历父项,直到它到达绑定元素。每次,它检查当前元素是否与选择器匹配,如果是,则调用处理程序。

所以你这样称呼它:

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

这是一个现场演示,它还添加了动态元素,以显示新元素也被拾取。

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>

这是为.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;            
    };
}

答案 1 :(得分:12)

这是与on()

的javascript 等效

<强>的jQuery

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

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

<强>的Javascript

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

通过这种方法,我们的想法是利用event.target。当然,随着选择器的改变,你的代码必须更多地参与其中

答案 2 :(得分:3)

在现代浏览器中,您可以使用https://pyautogui.readthedocs.io/en/latest/install.html来简化jQuery Element.closest()方法的复制,并确保从目标元素的子元素捕获事件冒泡(其他实现忽略的细微差别) 。较早的浏览器(包括IE)将需要.on()才能运行。

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>

答案 3 :(得分:0)

现代浏览器的另一种方法是:

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>

答案 4 :(得分:0)

我会提供对 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;
            }
        });
    }
}

通过切换最后 2 个参数,您可以在省略选择器时恢复默认的 addEventListener 行为。