使用本机 Javascript 实现 jQuery 的“实时”活页夹

问题描述 投票:0回答:6

我试图弄清楚如何将事件绑定到动态创建的元素。我需要事件在元素上持续存在,即使它被销毁并重新生成也是如此。

显然,使用 jQuery 的 live 函数很简单,但是用原生 Javascript 实现它们会是什么样子?

javascript jquery event-handling dom-events
6个回答
27
投票

这是一个简单的例子:

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

基本思想是你想要将一个事件处理程序附加到文档并让事件在 DOM 中冒泡。然后,检查

event.target
属性,看看它是否符合所需的条件(在本例中,只是元素的
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);
        }
    });
}

25
投票

除了 Andrew 的帖子和 Binyamin 的评论之外,也许这是一个选项:

有了这个,您可以使用“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'); });

14
投票

其他解决方案有点过于复杂......

document.addEventListener('click', e => {
   if (e.target.closest('.element')) {
       // .element has been clicked
   }
}

有一个 polyfill,以防您需要支持 Internet Explorer 或旧浏览器。


3
投票

将事件动态绑定到特定元素的替代方法可以是全局事件侦听器。因此,每次使用该元素上的另一个新元素更新 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>

在此示例中,我在

<ul>
上有一个用于单击事件的事件侦听器。因此,所有子元素都会发生一个事件。从我创建的简单事件处理程序中,您可以看到很容易添加更多逻辑、更多按钮(具有不同或重复的名称)、锚点等。

全力以赴,您可以将事件侦听器添加到文档而不是列表元素,捕获页面上的所有单击事件,然后在事件处理程序中处理单击事件。


0
投票

使用

.matches()
元素 api 会变得更简单。

const selector = '.item'

document.addEventListener('click', (e) => {
  if ( ! e.target.matches(selector) ) {
    return
  }

  // do stuff here
})

相当于 jQuery:

$('.item').live( 'click', (e) => {
  // do stuff here
})

0
投票

它是两者的组合,event.target可以是被点击的元素,或者它是它的子元素,或者都不是。所以混合匹配和最接近的在一起。

document.addEventListener('click', (e) => {
    const selector = '.button';
    const el = e.target.matches(selector) ? e.target : e.target.closest(selector);

    if (!el) return;
    
    // do something 
});
© www.soinside.com 2019 - 2024. All rights reserved.