寻找包含当前节点的jQuery find(..)方法


134

jQuery find(..)遍历方法不包括当前节点-它从当前节点的子级开始。调用在匹配算法中包括当前节点的查找操作的最佳方法是什么?查看文档,没有什么立即跳出来。

Answers:


153

对于jQuery 1.8及更高版本,您可以使用.addBack()。它需要一个选择器,因此您不需要过滤结果:

object.find('selector').addBack('selector')

在jQuery 1.8之前,您受困于.andSelf(),(现已弃用并删除),然后需要过滤:

object.find('selector').andSelf().filter('selector')

5
我将其捆绑为一个在插件中注册的插件jquery.findIncludeSelf。见github.com/ronen/jquery.findIncludeSelf
ronen 2014年

18
@ronen可以在一行中完成的额外文件吗?谢谢,但是不,谢谢。

6
@ prc322一个额外的文件对于部署将所有JavaScript捆绑到单个文件中的部署并没有困扰我。通常,即使是简单的事情,我也喜欢使用(经过测试的)库方法,而不是用我觉得更难阅读的东西弄乱我的代码,这会引入更多的错误可能性。特别是在这种情况下,恕我直言,需要指定'selector'两次使封装变得更加理想。YMMV
ronen

好的,所以我可能'selector'很胖,但是您不必指定两次(如@ronen所述),您不能只使用object.parent().find('selector')??? 吗?-话虽如此,我喜欢为您提供帮助的lib的想法。
山姆

8
@ circa1983 object.parent().find('selector')包括的兄弟姐妹object及其后代。
罗伯特

41

您不能直接执行此操作,我能想到的最接近的是使用.andSelf()和调用.filter(),如下所示:

$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);

不幸的.andSelf()是没有选择器,这很方便。


7
您甚至在回答了这个问题之后就在jQuery页面上添加了评论api.jquery.com/andSelf/#comment-50124533现在,这很彻底。真好!我做了我的尽职调查,也“喜欢”了那个。
约翰·K

2
第二个令人难以置信的缓慢。首先只是慢。
Tgr 2010年

@Tgr -我不反对,但先不应该是这个节目,除非你正在处理一个非常大的数目的元素。如果不需要链接,则可以肯定地跳过对这些元素的重新过滤。
尼克·克拉弗

3
有趣的是,closest(..)将当前DOM元素包括在树上,而将树等所有的遍历方法find(..)都与当前元素不匹配。似乎当两个操作一起用于完整垂直搜索时,jQuery团队有目的地实现了这些目标而没有重叠。
约翰·K

17
请记住,从v1.8开始不推荐使用.andSelf(),而将其替换为以选择器作为参数的.addBack()。参见api.jquery.com/addBack
kkara 2013年

9

定义

$.fn.findSelf = function(selector) {
    var result = this.find(selector);
    this.each(function() {
        if ($(this).is(selector)) {
            result.add($(this));
        }
    });
    return result;
};

然后使用

$.findSelf(selector);

代替

$find(selector);

遗憾的是,jQuery没有此内置函数。这么多年的发展真的很奇怪。由于.find()的工作原理,我的AJAX处理程序未应用于某些顶级元素。


这是越野车。即使其中只有一个匹配,它也会添加所有“自我” ...-此错误的一个原因是一个app脚的jQuery方法...
Robert Siemer

我试图修复您报告的错误。现在可以正常使用吗?
Dmitriy Sintsov

大多数其他答案都在此使用filter(),这更有意义。
罗伯·西默

5
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))

您可以将其存储$('selector')在变量中以加快速度。如果您非常需要它,您甚至可以为此编写一个自定义函数:

$.fn.andFind = function(expr) {
  return this.find(expr).add(this.filter(expr));
};

$('selector').andFind('otherSelector')

不过,这仅在您以选择器开始时才有效,但事实并非如此。另外,这不正确,那就是$('selector').find('otherSelector').add($('otherSelector')),您现在拥有的等同于.andSelf()。最后,.andFind()不要根据表达式进行过滤,您需要.add($(this).filter(expr)):)
尼克·克雷弗

@Nick Craver:是的,我忘记了过滤部分,现在已修复。可以$('selector')用其他方法来获取jQuery对象(如果不是通过选择器开始的意思)来代替它,则add()可以处理任何内容$()
Tgr 2010年

我的观点是,您$('selector')可能是$('selector').children('filter').closest('.class').last()……可能处于一个链中,并且您不知道要添加的对象是什么,因此通用解决方案应该像过滤器一样使用先前的对象:)
Nick Craver

我仍然不明白为什么这会是一个问题。this是调用插件的任何jQuery对象。也可能是呼叫链的结果。
Tgr 2010年

5

可接受的答案效率很低,并且会过滤已匹配的元素集。

//find descendants that match the selector
var $selection = $context.find(selector);
//filter the parent/context based on the selector and add it
$selection = $selection.add($context.filter(selector);

3

如果您希望链接正常工作,请使用以下代码段。

$.fn.findBack = function(expr) {
    var r = this.find(expr);
    if (this.is(expr)) r = r.add(this);
    return this.pushStack(r);
};

在调用end函数之后,它返回#foo元素。

$('#foo')
    .findBack('.red')
        .css('color', 'red')
    .end()
    .removeAttr('id');

如果没有定义额外的插件,您将陷入困境。

$('#foo')
    .find('.red')
        .addBack('.red')
            .css('color', 'red')
        .end()
    .end()
    .removeAttr('id');

啊,不...如果满足this一个以上的元素,this.is()但只有其中一个匹配。
罗伯·西默

3

如果您要查找的是一个元素(当前元素或其中一个元素),则可以使用:

result = elem.is(selector) ? elem : elem.find(selector);

如果您正在寻找多个元素,可以使用:

result = elem.filter(selector).add(elem.find(selector));

andSelf/ 的使用andBack非常少见,不确定为什么。也许由于性能问题,有些人在我之前提到过。

(我现在注意到Tgr已经给出了第二个解决方案)


2

我知道这是一个老问题,但是有一个更正确的方法。如果顺序很重要,例如,当您匹配像这样的选择器时:first,我写了一个小函数,它将返回与find()实际包含当前元素集完全相同的结果:

$.fn.findAll = function(selector) {
  var $result = $();

  for(var i = 0; i < this.length; i++) {
    $result = $result.add(this.eq(i).filter(selector));
    $result = $result.add(this.eq(i).find(selector));
  }

  return $result.filter(selector);
};

无论如何它都不会高效,但是这是我维护正确订单的最佳方法。


1

我想andSelf是你想要的:

obj.find(selector).andSelf()

请注意,这将始终添加当前节点,无论它是否与选择器匹配。



0

我试图找到一个不会重复解决方案(即不两次输入相同的选择器)。

这个微小的jQuery扩展做到了:

jQuery.fn.findWithSelf = function(...args) {
  return this.pushStack(this.find(...args).add(this.filter(...args)));
};

它结合了find()(仅是后代)和filter()(仅是当前集合),并支持两者都吃掉的参数。该pushStack()允许.end()工作预期。

像这样使用:

$(element).findWithSelf('.target')

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.