javascript - 将 jQuery.on(event,selector,func) 转换为 .addEventListener(event, func) 尤其是 DOM 树之后的选择器部分和事件气泡
问题描述
我想将我项目中的代码从jQuery.on
to转换为.addEventListener
并删除对 jQuery 的依赖。
主要问题:有没有办法用相对较少的代码来做到这一点,或者我是否需要像 jQuery 那样编写自定义事件处理?
------------------------------------------
| a |
| |
| ----------------------------- |
| | b | |
| | | |
| | --------------- | |
| | | c | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | --------------- | |
| | | |
| | | |
| ----------------------------- |
| |
| |
------------------------------------------
点击c应该返回 c 的处理程序,然后是b然后是 a
我已经阅读了多个 stackoverflow 问题*和答案,它们让我对两者之间的差异有一个基本的了解(或者主要是 jQuery 添加的附加逻辑)。在这个小提琴中,您可以看到一个基本示例,我想以 jQuery 的工作方式工作。
我很div.c
清楚div.a
,当事件从目标(就像 jQuery 一样。div.a
b是粗体,因为它不会被触发,尽管这应该是期望的行为。它没有被触发的原因是 e.target( div.c
) 与 querySelector 不匹配.b
。
对我来说,当从.addEventHandler
. 即使监听器是从一个共同的父级触发的,它似乎也考虑了 DOM 嵌套。考虑到 DOM 嵌套的最后一部分是我希望使用 'vanilla' js 的内容。
使用$._data(element, 'events')
我们可以访问 jQuery 内部存储的事件以查看它们。这里的guid
属性似乎表明了事件被触发的顺序。订单是如何确定/触发的,但是我找不到。
非常感谢任何帮助!
*
相关问题
jQuery .on(); 与 JavaScript .addEventListener();
解决方案
您可以遍历 target 的所有祖先并检查它们是否匹配特定的选择器并为每个匹配的实例调用回调
它们触发的顺序仍然是它们添加到根元素的顺序
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>
请注意,这在生产中未经测试
推荐阅读
- java - 执行 AsyncTask 时无法解析符号“执行”
- jenkins-pipeline - 共享库“vars”文件夹结构 - 我可以添加子文件夹吗?
- angular - Angular - 自定义 ngx-bootstrap Typeahead 以根据逗号分隔的多个值自动完成
- java - 视图关闭时如何杀死从 JavaFX 控制器产生的线程
- r - R中的Levene事后测试
- spring - 没有@Qualifier 的@AutoWired
- php - 密码重置在验证时不返回错误消息
- uwp - 向任意方向旋转图像和画布笔划 90 度
- gitlab - gitlab-runner 命令生命周期以重新启动运行器
- java - 为什么@EnableWebMvc 会破坏 JSON 反序列化?