如何选择一个元素的父级和父级的兄弟节点?

54

我有这段代码:

$("#test").siblings('p').remove();
$("#test").remove();

我该如何将这段代码链接起来,而不是分开写?

7个回答

85

在这种情况下,您想要使用addBack()

$("#test").siblings('p').addBack().remove();

编辑

首先,对于未来的访问者,如果您使用的是jQuery版本1.8及以下,则可能需要使用andSelf()而不是addBack()以解决兼容性问题。

其次,在这种情况下,endaddBack都能完成相同的任务,但它们实际上是不同的视角。看一下这个HTML:

<div class="grandpa">
    <div class="dad">
        <div class="son">
            Test
        </div>
    </div>
</div>

如果我们正在使用 end()

$('.grandpa')
    .find('.dad')
        .find('.son')
        .addClass('youngster')
        .end()
    .addClass('adult')
    .end()
.addClass('oldster');

结果将会如下所示:

<div class="grandpa oldster">
    <div class="dad adult">
        <div class="son youngster">
            Test
        </div>
    </div>
</div>  

使用end()方法时,我们告诉jQuery它需要返回到父级元素集合dad,并为其添加一个adult类,而这个父级元素集合是从当前的son元素遍历回来的。

但当我们使用addBack方法时:

$('.grandpa')
    .find('.dad')
        .find('.son')
        .addClass('youngster')
        .addBack()
        .addClass('adult')
        .addBack() // This simply do nothing since `addBack` is not traverse up DOM element 
        .addClass('oldster');    

这将导致如下结果:

<div class="grandpa">
    <div class="dad adult oldster">
        <div class="son youngster adult oldster">
            Test
        </div>
    </div>
</div>

因此,当我们在son上调用addBack时,我们告诉jQuery将dadson放入同一房间,并向它们两个添加新的类adultoldster


2
.end().addBack()更合适吗? - RoToRa
@RoToRa 在这种情况下,它们都是做同样的事情。 - Eli

16

end() 方法主要在使用 jQuery 链式语法时非常有用。如果不使用链式语法,我们通常可以通过变量名直接调用先前的对象,因此不需要操作堆栈。

新的元素集将被推入维护在对象内部的堆栈中。每个连续的过滤方法都会将一个新的元素集推入堆栈。如果我们需要一个旧的元素集,可以使用 end() 将集合从堆栈中弹出。

我猜像这样使用 .end()

$("#test").siblings('p').remove().end().remove();

您可以在fiddle上找到。


一些解释:

现在这段代码发生了什么:

假设这是HTML标记:

```
<div id='container'>
   <div id='test'>This is supposed to be removed.</div>
   <p>And this to be removed too.</p>
</div>

当脚本执行时:

$("#test").siblings('p').remove()

这个块会从视图中移除同级项<p>,然后标记将被更新如下:

<div id='container'>
   <div id='test'>This is supposed to be removed.</div>
</div>

并且如果我们将其与 .end() 链接在一起

$("#test").siblings('p').remove().end()

它返回到堆栈中的 #test div,然后脚本的下一部分被触发。

$("#test").siblings('p').remove().end().remove();
                             //--^^^^^^^^^^^^^^^----this next part

同时#test 从视图中删除,最终的输出标记将如下:

<div id='container'>
</div>

10

可能与主题无关...但是你可以改变问题的视角:

$("#test, #test ~ p").remove(); // !! incorrect way, see comment below

对不起各位 :( 我的决定是错误的!!

选择器 '~' 不等同于 'sibling' 方法。'~' 选择所有在 '#test' 元素之后的兄弟 'p' 元素。

因此,我建议另一个决定:

$("#test, > p", $('#test').parent()).remove();

这种方法可能不够优雅,但是它是最快的。请查看 'http://jsperf.com/how-to-chain-this-code-stackoverflow-16009101'。

性能测试结果:

Performance test result

附注:http://jsfiddle.net/Dpe59/


1
我喜欢这个答案 - 完成工作,而不使用更多的jQuery结构。 - alonisser

7

我同意对问题的评论;为了可读性和可维护性,请使用andSelf

$("#test").siblings('p').andSelf().remove();

很遗憾,它已经被弃用了。但是如果你像我们一样被困在旧版本的jquery上,它可能是值得的。


1
$("#text").siblings('p').remove().prevObject.remove();

编辑: 虽然这个方法可以运行,但是不要这样做。正如Matt的评论所说,prevObject没有被记录在文档中。


请注意,prevObject是完全未记录的;它可能会在以后的版本中更改或删除。另一方面,end()是有文档记录的,并且是返回到前一个jQuery对象的首选方法。 - Matt

1
$("#test").siblings("p").siblings("#test").remove();

在某些情况下,这也是一种选择 :) - Mihai
你的决定不正确,它只会删除“#test”元素。请检查一下。 - vladimir

0
尝试这个:
$("#test").siblings('p').addBack().remove();

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