我正在寻找最精彩的主意。重点是效率 - 让我们试着避免一堆循环=)
没有图书馆。这是一个纯JS天才的练习。如果他们完成了这个,可以随意引用库中的函数。不需要对糟糕的旧浏览器(即:IE)进行回退。
设置
我正在尝试创建事件委托。我将事件侦听器绑定到此元素中发生的每个事件类型的容器元素(上下文)(单击,鼠标中等)。监听器引用一个函数,我们称之为“路由”。
有一个对象,单独创建,看起来像这样(例子):
myarr['click']['.myclass'] = functionReference1;
myarr['click']['#myid'] = functionReference2;
myarr['click']['div>a'] = functionReference3;
route
需要event.type
(此处为“点击”)并转到myarr并获取所有click
条记录。 route
然后遍历每个选择键并将其与event.target
匹配。如果匹配,则调用函数引用,如果愿意,则调用callback
。
这一切都很好。相当快速,直截了当。
问题
event.target
可能是与选择键匹配的元素的子元素。我正在寻找疯狂平滑的伏都教黑魔法,以确定父母是否在我们的上下文元素和event.target
之间。优选地,一些本机浏览器功能。
理想,例如,我可以按照
的方式做点什么 context.querySelectorAll(key + " " + event.target);
但很明显,据我所知,我无法将对象传递给querySelectorAll。
已尝试的内容
尝试了两种方法。两个都工作。两者都不漂亮。
1)
循环遍历event.target.parentNode,直到找到匹配项。这个手提包可以做到,但它在我现有的循环中创建了一个循环。当页面上有多个选择键和许多元素时,开始变慢。
if (event['target'].matchesSelector(key)) {
//do callback
} else {
var et = event['target'];
while (et['parentNode'] !== null and et['parentNode'] !== this) {
et = et['parentNode'];
if (et.matchesSelector(key)) {
//do callback
break;
}
}
}
2)
使用范围。我为这个问题感到自豪,但它有同样的多循环问题。没有过多地测试性能,但是这里发生了很多事情,如果有很多元素匹配选择键,这可能会损害效率。
if (event['target'].matchesSelector(key)){
//do callback
} else {
var range2 = document.createRange();
range2.selectNode(event.target);
var range = document.createRange();
var allthese = document.querySelectorAll(key)
for (var i = 0; i < allthese.length; i++){
range.selectNode(allthese[i]);
if (range2.compareBoundaryPoints(range2.START_TO_START, range) && range2.compareBoundaryPoints(range2.END_TO_END, range) <= 0){
//do callback
break;
}
}
}
MAGIC VOODOO - 找我一些,当我再次拥有代表时,我会创造一笔巨额赏金。
答案 0 :(得分:3)
也许你应该试试这个:
event['target'].matchesSelector(key) || event['target'].matchesSelector(key + ' *')
这里我的第二个条件是检查目标是否是键选择器的后代
正如您在此JSFIDDLE中所看到的(仅限webkit中的小提琴作品(仅限Chrome)浏览器)使用父选择器匹配子/后代
PS:如果您还需要与实际键匹配的元素,此方法将不起作用,但在您的问题中,您说“疯狂平滑巫毒黑魔法,以确定该父级是否在我们的上下文元素和event.target之间” ,所以我想你不需要实际的元素
答案 1 :(得分:1)
这个怎么样:
if (event['target'].matchesSelector(key)) {
//do callback
} else {
var allthese = document.querySelectorAll(key) //this array has order
//use "binary search" here to improve perfomance.
for (var i = 0; i < allthese.length; i++){
if(event['target'].compareDocumentPosition(allthese[i])&&DOCUMENT_POSITION_CONTAINS){
//do callback
}
}
}
}
您可以使用二进制搜索之类的算法来提高性能(所有这些都是有序数组)。
compareDocumentPosition的返回值为:
因此,您可以使用搜索算法搜索该数组“document.querySelectorAll(key)”。