jQuery选择后代元素,包括父元素

24

考虑以下 HTML 代码:

<div class="foo" id="obj">
   I should be changed red
   <div class="bar" style="color:black;">
      I should not be changed red.
      <div class="foo">I should be changed red.</div>
   </div>
</div>

如何选择DOM元素obj和一个表达式的所有子元素,包括可能的obj本身?我需要类似于“选择后代”的东西,但也包括父元素,如果它匹配该表达式。

var obj = $("#obj")[0];

//wrong, may include siblings of 'obj'
$(".foo", $(obj).parent()).css("color", "red");

//wrong -- excludes 'obj'
$(".foo", obj).css("color", "red");

//correct way, but it's annoying
var matches = $(".foo", obj);
if ($(obj).is(".foo")) matches = matches.add(obj);
matches.css("color", "red");

有没有更优雅的解决方案?


1
+1:好问题。今天遇到了这种情况。已经采纳了Andrew的答案和你的评论,并添加了一个微不足道的jQueryfindAndSelf扩展,正如你建议的那样供所有人使用。干杯。 - iCollect.it Ltd
8个回答

28

如果我理解你的意思正确:

$(currentDiv).contents().addBack('.foo').css('color','red');

为了更清晰,我将 "div" 重命名为 "currentDiv"。这会选择当前元素及其包含的所有元素,然后过滤掉没有类别为foo的元素,并将样式应用于剩余的元素,即具有foo类别的元素。

编辑:略微优化

$(currentDiv).find('.foo').addBack('.foo').css('color','red');

编辑

此答案已更新,包括最新的jQuery方法。它原先是:

$(currentDiv).find('.foo').andSelf().filter('.foo').css('color','red');

对于jQuery 1.8之前的版本,仍需要使用它。


1
啊,谢谢... "andSelf()" 是我缺少的部分。不幸的是,这种方法效率低下...需要遍历所有子元素才能筛选,而不是只需一次遍历即可。 - Sam
1
这仍然比addback(JQ 1.8及更高版本)略逊一筹,因为它在后代上第二次运行filter,尽管它们已经全部匹配。 - iCollect.it Ltd
Note: This function has been deprecated and is now an alias for .addBack(), which should be used with jQuery 1.8 and later - dsdsdsdsd

9

jQuery 1.8引入了.addBack(),它接受一个选择器,代替了.andSelf()。因此,tvanfosson的代码变得更加高效。

$(currentDiv).find(".foo").addBack(".foo").css("color", "red");

如果你没有这个,我认为
$(currentDiv).find(".foo").add(currentDiv.filter(".foo")).css("color", "red");

如果不考虑美观,这将非常高效。

1
肯定更喜欢 jQuery 1.8。已经根据您的建议添加了一个名为 findAndSelf 的 jQuery 扩展方法。使用 addBack 效果非常好,全归功于您。干杯 :) - iCollect.it Ltd

2

Andrew的回答非常有用,也是所有答案中最有效的(从jQuery 1.8开始),所以我像Sam建议的那样,将其转换为一个简单的jQuery扩展方法供大家使用:

扩展代码:

jQuery.fn.findAndSelf = function (selector){
    return this.find(selector).addBack(selector);
};

使用方法:

$(function(){
    $('#obj').findAndSelf('.foo').css('color', 'red');
});

JSFiddle: http://jsfiddle.net/BfEwK/

特别感谢Andrew建议使用addBack()作为最佳选项(截至目前为止)。已经给他点赞并建议大家也这样做。


1
怎么没人注意到这个呢?你应该得到一个拥抱和高五。 - The Dembinski
1
@TheDembinski:感谢您的拥抱(但我不会高五哦):) - iCollect.it Ltd

1
一种更简短的方法来选择所有后代元素,包括父元素:
$('*', '#parent').addBack();

这与以下内容相同:

$('#parent').find('*').addBack();

$('*', '#parent').addBack().css('border', '1px solid #f00');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
  <span>Child</span>
  <span>Another child</span>
</div>

当然,您可以将通用选择器更改为所需的元素。

$('.foo', '#parent').addBack();

或者

$('#parent').find('.foo').addBack();

1
除非有更好的解决方案,否则我已经创建了一个新函数并使用它来代替 $。
var _$ = function(expr, parent){ 
   return $(parent).is(expr) ? $(expr, parent).add(parent) : $(expr, parent); 
}

3
我会使用这个并扩展jQuery来创建一个“findAndSelf()”或类似的函数。 - Sam
已经应用了你提供的findAndSelf建议(好名字)到 Andrew 的答案上,并发布供大家剪切粘贴。 - iCollect.it Ltd

0

如果我没记错的话,你不是可以只做以下操作吗?

$("#obj").css("color", "red").find(".foo").css("color", "red");

找到预定的对象/元素应用CSS,然后找到该对象/元素中所有对象/元素使用该选择器,并将CSS应用于它?


不,他们只想选择父元素*如果它也有.foo*,但是你的代码包括了所有情况。 - iCollect.it Ltd

-1
 $('div.foo, div.foo > *').css('color','red');

主要思想是您可以通过逗号将不同的规则分开匹配。就像在 css 中一样。据我所知,jquery 支持 这里 中的所有内容,并且可以通过逗号分隔进行“OR”操作。


这将选择文档中的所有 .foo,以及 .foo 的所有子元素。 - Sam
没错...我以为你是这个意思。 - rz.
啊,抱歉,我已经澄清了问题。 - Sam
现在答案是:所有class为foo的div及其所有子元素。满意吗? - rz.
答案是“所有与[表达式]匹配的[some object]的子对象以及如果[some object]匹配[expression],则包括[some object]本身”。 - Sam

-1

这难道不是你想要的吗(除非我误解了...)

$(document).ready(function(){
    $("div.foo").css("color", "red");
});

这个可以“工作”,但只是因为在示例中它们碰巧都是divs。问题是如何包括初始元素(如果匹配)以及任何后代元素(也匹配)。如果#obj之外还有更多.foo,它们也会被包括进来(这不是期望的行为)。 - iCollect.it Ltd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接