javascript - 将 jQuery.on(event,selector,func) 转换为 .addEventListener(event, func) 特别是 DOM 树后面的选择器部分和事件气泡

标签 javascript jquery addeventlistener dom-events jquery-events

我想将项目中的代码从 jQuery.on 转换为 .addEventListener 并删除对 j​​Query 的依赖。

主要问题:有没有一种方法可以用相对较少的代码来完成此操作,或者我是否需要编写像 jQuery 那样的自定义事件处理?

------------------------------------------
|                   a                    |
|                                        |
|     -----------------------------      |
|     |             b             |      |
|     |                           |      |
|     |      ---------------      |      |
|     |      |      c      |      |      |
|     |      |             |      |      |
|     |      |             |      |      |
|     |      |             |      |      |
|     |      |             |      |      |
|     |      |             |      |      |
|     |      ---------------      |      |
|     |                           |      |
|     |                           |      |
|     -----------------------------      |
|                                        |
|                                        |
------------------------------------------

点击c应该返回c的处理程序,然后是b,然后是a

我已经阅读了多个 stackoverflow 问题*和答案,它们让我对两者之间的差异(或者主要是 jQuery 添加的附加逻辑)有了基本的了解。在此fiddle您可以查看一个基本示例,我希望以 jQuery 的方式工作。

我很清楚,当事件从目标 (div.c) 冒出时,它会到达 div.a,然后到达 div 上的监听器.a 按照它们添加的顺序被触发,在本例中结果是 a、b、c,而不是像 jQuery 那样的 c、b、a。

b 是粗体,因为它不会被触发,尽管这应该是期望的行为。 它没有被触发的原因是 e.target (div.c) 与 querySelector .b 不匹配。

对我来说,当事件从 .addEventHandler 触发时,jQuery 使用自己的事件句柄/触发。 尽管监听器是从公共(public)父级触发的,但似乎还是考虑了 DOM 嵌套。 考虑 DOM 嵌套的最后一部分是我希望使用“vanilla”js 实现的。

使用 $._data(element, 'events') 我们可以访问 jQuery 内部存储的事件来查看它们。 这里的guid属性似乎表明了事件被触发的顺序。 但是我无法找到如何确定/触发订单。

非常感谢任何帮助!

*相关问题

jQuery .on(); vs JavaScript .addEventListener();

jQuery event handlers always execute in order they were bound - any way around this?

jQuery on() stopPropagation not working?

最佳答案

您可以遍历目标的所有祖先并检查它们是否与特定选择器匹配,并为每个匹配实例调用回调

它们触发的顺序仍然是它们添加到根元素的顺序

HTMLElement.prototype.delegate = function(evtName, selector, callback) {
  var rootElement = this;


  this.addEventListener(evtName, function(e) {
    var matchingAncestors = [], parent = e.target.parentElement;
    // TODO: Abort if target is root element

    if (e.target.matches(selector)) {
       console.log('selector', selector,'matches target')
      callback(e)
    } else {
      // we know it's not the target so work way up ancestors finding selector matches     
      while (parent && parent !== rootElement) {
        if (parent.matches(selector)) {
          matchingAncestors.push(parent)
        }
        parent = parent.parentElement
      }

      // call the callback for each instance
      matchingAncestors.forEach(function(el) {
        console.log(el, ' is matching ancestor of target')
        callback(e)
      });
    }
  })

}
   
var a = document.querySelector(".a");

a.addEventListener("click", function(e) {
  console.log('*********************************')
  console.log("Vanilla a\n");
});
a.delegate('click', '.b', function(e) {
  console.log("Vanilla-delegate b\n");
})

a.delegate('click', '.c', function(e) {
  console.log("Vanilla-delegate c\n");
})
div {padding-left:30px; border:1px solid #ccc}
<div class="a">
  a
  <div class="b">
    b
    <div class="c">
      c<br>(click me)
    </div>
  </div>
</div>

请注意,这在生产中未经测试

关于javascript - 将 jQuery.on(event,selector,func) 转换为 .addEventListener(event, func) 特别是 DOM 树后面的选择器部分和事件气泡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51351646/

相关文章:

javascript - 包装一对具有相似类名的 <span>

asp.net - 如何从 Jquery Ajax 调用 Default.aspx.cs 页面方法?

单击时移动的按钮的 JavaScript addEventListener "click"

javascript - 无法在自己的自定义插件中触发点击功能

javascript - 如何使用 Javascript/Node.js 从网站获取对象?

javascript - 使用动态 PHP 变量绘制流程图绘图点

javascript - jQuery/Javascript 如果宽度问题

javascript - 动态下拉列表 - 想要一种将输入存储在变量中的方法

javascript - 隐藏在 Bootstrap 导航栏后面的 jQuery 自动完成建议框

javascript - 是否可以扩展 EventTarget 接口(interface)?