使用原生 Javascript 实现 jQuery 的“实时”活页夹
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9106329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Implementing jQuery's "live" binder with native Javascript
提问by jjhenry
I am trying to figure out how to bind an event to dynamically created elements. I need the event to persist on the element even after it is destroyed and regenerated.
我想弄清楚如何将事件绑定到动态创建的元素。即使在元素被销毁和重新生成后,我也需要该事件在元素上持续存在。
Obviously with jQuery's live function its easy, but what would they look like implemented with native Javascript?
显然,使用 jQuery 的 live 函数很容易,但是使用原生 Javascript 实现它们会是什么样子?
回答by Andrew Whitaker
Here's a simple example:
这是一个简单的例子:
function live(eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
if (event.target.id === elementId) {
cb.call(event.target, event);
}
});
}
live("click", "test", function (event) {
alert(this.id);
});
The basic idea is that you want to attach an event handler to the document and let the event bubble up the DOM. Then, check the event.target
property to see if it matches the desired criteria (in this case, just that the id
of the element).
基本思想是您希望将事件处理程序附加到文档并让事件在 DOM 中冒泡。然后,检查event.target
属性以查看它是否符合所需的条件(在这种情况下,只是id
元素的 )。
Edit:
编辑:
@shabuncdiscovered a pretty big problem with my solution-- events on child elements won't be detected correctly. One way to fix this is to look at ancestor elements to see if any have the specified id
:
@shabunc在我的解决方案中发现了一个相当大的问题——无法正确检测到子元素上的事件。解决此问题的一种方法是查看祖先元素以查看是否有指定的id
:
function live (eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
var el = event.target
, found;
while (el && !(found = el.id === elementId)) {
el = el.parentElement;
}
if (found) {
cb.call(el, event);
}
});
}
回答by Ro NL
In addition to Andrew's post and Binyamin's comment, maybe this is an option:
除了 Andrew 的帖子和 Binyamin 的评论之外,也许这是一个选项:
With this you can use 'nav .item a' as the selector. Based on Andrew's code.
有了这个,您可以使用“nav .item a”作为选择器。基于安德鲁的代码。
function live (eventType, elementQuerySelector, cb) {
document.addEventListener(eventType, function (event) {
var qs = document.querySelectorAll(elementQuerySelector);
if (qs) {
var el = event.target, index = -1;
while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) {
el = el.parentElement;
}
if (index > -1) {
cb.call(el, event);
}
}
});
}
live('click', 'nav .aap a', function(event) { console.log(event); alert('clicked'); });
回答by chrwahl
An alternative to binding an event to dynamically to a specific element could be a global event listener. So, each time you update the DOM with another new element event on that element will also the "catches". An example:
将事件动态绑定到特定元素的替代方法可能是全局事件侦听器。因此,每次使用该元素上的另一个新元素事件更新 DOM 时,也会“捕获”。一个例子:
var mybuttonlist = document.getElementById('mybuttonlist');
mybuttonlist.addEventListener('click', e=>{
if(e.target.nodeName == 'BUTTON'){
switch(e.target.name){
case 'createnewbutton':
mybuttonlist.innerHTML += '<li><button name="createnewbutton">Create new button</button></li>';
break;
}
}
}, false);
ul {
list-style: none;
padding: 0;
margin: 0;
}
<ul id="mybuttonlist">
<li><button name="createnewbutton">Create new button</button></li>
</ul>
In this example I have an event listener on the <ul>
for click events. So, an event happens for all child elements. From the simple event handler I created, you can see that it is easy to add more logic, more buttons (with different or repeating names), anchors etc.
在这个例子中,我有一个<ul>
关于点击事件的事件监听器。因此,所有子元素都会发生一个事件。从我创建的简单事件处理程序中,您可以看到添加更多逻辑、更多按钮(具有不同或重复名称)、锚点等很容易。
Going all in, you could add the eventlistener to document instead of the list element, catching all click events on the page and then handle the click events in the event handler.
总而言之,您可以将事件侦听器添加到文档而不是列表元素,捕获页面上的所有点击事件,然后在事件处理程序中处理点击事件。
回答by Fabian von Ellerts
The other solutions are a little overcomplicated...
其他解决方案有点过于复杂......
document.addEventListener('click', e => {
if (e.target.closest('.element')) {
// .element has been clicked
}
}
There is a polyfillin case you need to support Internet Explorer or old browsers.
如果您需要支持 Internet Explorer 或旧浏览器,可以使用polyfill。