3

我正在寻找最绝妙的主意。重点是效率- 让我们尽量避免一堆循环 =)

没有图书馆。这是纯 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 - 找我一些,当我再次获得代表时,我会创造一个大赏金。

4

2 回答 2

3

也许你应该试试这个:

event['target'].matchesSelector(key) || event['target'].matchesSelector(key + ' *')

这里我的第二个条件将检查目标是否是键选择器的后代

正如您在这个JSFIDDLE中看到的(fiddle Works in webkit(prefer chrome)仅浏览器),使用父选择器匹配子/后代

PS:如果您还需要与实际键匹配的元素,则此方法将不起作用,但是在您的问题中,正如您所说的“疯狂平滑的巫术黑魔法,以确定该父项是否在我们的上下文元素和 event.target 之间”,所以我假设您不需要实际元素

于 2012-11-13T19:31:10.917 回答
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_POSITION_DISCONNECTED 1
  • DOCUMENT_POSITION_PRECEDING 2
  • DOCUMENT_POSITION_FOLLOWING 4
  • DOCUMENT_POSITION_CONTAINS 8
  • DOCUMENT_POSITION_CONTAINED_BY 16
  • DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32

因此,您可以使用搜索算法搜索该数组“document.querySelectorAll(key)”。

于 2013-04-02T10:19:01.090 回答