【问题标题】:Is this the best way to query an element and its children?这是查询元素及其子元素的最佳方式吗?
【发布时间】:2010-05-29 18:38:19
【问题描述】:

我正在尝试查询一个元素它的子元素以查找以特定字符串开头的 ID。

var foundIDs = containerElement.find('[id^=something]').andSelf().filter('id^=something');

find() 方法只搜索后代,所以我想我会尝试andSelf()。但是,andSelf() 不采用选择器。这意味着无论容器元素是否与查找查询匹配,都会包含容器元素,然后我必须对其执行辅助filter() 以删除容器元素(如果它根本不匹配)。

我试图将andSelf() 之前 放在find() 之前,但它似乎没有将容器元素放入堆栈。

containerElement.andSelf().find('[id^=something]');

有没有更好的方法来实现我正在做的事情?

【问题讨论】:

    标签: javascript jquery filter jquery-selectors


    【解决方案1】:

    就在我的脑海中(未测试):

    var foundIDs = containerElement
                         .filter('id^=something')
                         .add(containerElement.find('id^=something'));
    

    这并没有比你第一次尝试更有效率,但我认为它更干净一些。

    【讨论】:

    • 我想不可避免地不得不使用同一个选择器两次。
    【解决方案2】:
    containerElement.find('*').andSelf().filter('[id^=something]');
    

    【讨论】:

    • 有道理,但我在 find 中带有选择器的版本会减少查询集,以便过滤器稍后处理更少。
    【解决方案3】:

    我知道你已经接受了一个答案,但无论如何我都会把这个扔掉。

    var foundIDs = containerElement.wrap('<div>')             // Wrap
                                   .parent()                  // Traverse up
                                   .find('[id^=something]');  // Perform find
    
    containerElement.unwrap();  // DOM is untouched
    

    因为您在函数完成之前解开 containerElement,所以 DOM 保持不变(如果您想知道的话)。

    我用livequery 插件验证了它,它永远不会检测到新的div

    如果您记录 foundID 的 ID(或其他),您会看到顶层是您的 containerElement(假设它符合 .find() 标准。

    console.log( foundIDs.attr('id') );  // Log the ID of the root element.
    

    编辑:

    关于测试,我针对只有 2 个嵌套元素的 containerElement 在两个版本上执行了 1,000 次迭代循环。

    我只在 Mac 上的 Safari 中测试过。

    接受的答案大约快 7 倍。

    如果我添加 100 个嵌套元素,差距缩小到不到 2 倍。

    问题来了。如果 containerElement 不匹配,两个版本都返回 0 个元素。我不确定这是为什么。

    【讨论】:

    • 聪明,但感觉相当hackish。我想知道堆栈上会产生什么样的性能影响?
    • @Soviut - 好问题。我做了一个小测试。我会用我非正式的、半不科学的结果来更新我的答案。需要注意的一件事是,如果containerElement.find() 中的选择器不匹配,则接受的答案似乎完全失败。
    • @Soviut - 忽略我的 cmets 关于选择器失败的问题。我犯了一个愚蠢的错误。虽然我找到了比这两个答案更快的方法。我会把它贴在我的答案的顶部。
    • 您应该将其作为第二个答案发布以减少混乱。这样两者都可以被赞成。
    • @Soviut - 谢谢。做了一点整理。 :)
    【解决方案4】:

    这个比我的另一个答案有更好的性能,但是你失去了你接受的答案提供的链接能力。

        // Do a typical find.
    var found = containerElement.find('[class^=something]');
    
        // Test the containerElement directly,
        //    and push it into the 'found' object if it matches.
    if( containerElement.is('[class^=something]') ) found.push(containerElement);
    

    【讨论】:

    • 由于我如何处理收到的 'each()' containerElement,我试图在一个查询中完成所有操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    相关资源
    最近更新 更多