【问题标题】:How do I remove descendant elements from a jQuery wrapped set?如何从 jQuery 包装集中删除后代元素?
【发布时间】:2011-02-18 19:02:51
【问题描述】:

当我试图选择一个元素,然后从包装的集合中删除某些后代元素时,我对使用哪个 jQuery 方法和/或选择器有点困惑。

例如,给定以下 HTML:

<div id="article">
  <div id="inset">
    <ul>
      <li>This is bullet point #1.</li>
      <li>This is bullet point #2.</li>
      <li>This is bullet point #3.</li>
    </ul>
  </div>
  <p>This is the first paragraph of the article</p>
  <p>This is the second paragraph of the article</p>
  <p>This is the third paragraph of the article</p>
</div>

我要选择文章:

var $article = $('#article');

然后从包装集中删除&lt;div id="inset"&gt;&lt;/div&gt; 及其后代。我尝试了以下方法:

var $article = $('#article').not('#inset');

但这不起作用,回想起来,我想我明白为什么了。我也尝试使用remove() 失败。

这样做的正确方法是什么?

最终,我需要以可以定义配置数组的方式进行设置,例如:

var selectors = [
  {
    select: '#article',
    exclude: ['#inset']
  }
];

其中select 定义包含文本内容的单个元素,exclude 是一个可选数组,它定义一个或多个选择器以忽略其中的文本内容。

鉴于最终包装集已移除排除元素,我希望能够调用 jQuery 的 text() 方法以得到以下文本:

这是文章的第一段。
这是文章的第二段。
这是文章的第三段。

配置数组不需要完全像那样工作,但它应该提供大致等效的配置潜力。

感谢您提供的任何帮助!

【问题讨论】:

  • 抱歉有任何歧义 - 我想选择#article,然后删除#inset 中的任何内容。最终,我想从#article 中提取除#inset 中的所有文本。

标签: javascript jquery dom jquery-selectors css-selectors


【解决方案1】:

如果您想删除#article 中的任何内容,但使用#inset:

$('#article > *:not(#inset)').remove() // selects all direct children of #article but not #inset and removes them

在此处查看示例:http://jsfiddle.net/zwPsD/

如果想将此规则应用于多个 DOM 元素,您可以将它们链接起来:

$('#article, #article2, #article3, #etc').find('> *').not('#inset, #that, #and. #there').remove()

你可以在这里找到一个例子: http://jsfiddle.net/ZNjdE/

通过简单的 each 你可以提取文本: http://jsfiddle.net/ZNjdE/2/

【讨论】:

  • 谢谢,meo - 请参阅我对原始帖子的评论以澄清我的目标。不过,您的解决方案似乎只适用于#article 的直接子代。我将如何删除可以处于任何级别的后代?例如,如果在#article#inset 之间存在另一个&lt;div&gt; 怎么办?
  • 感谢您的帮助,meo - 这个答案对我非常有用,尽管我最终选择了 PeterTheNiceGuy 的方法,因为它更适合我的项目的特定要求。感谢您的帮助!
【解决方案2】:

试试这样的。

$('#article').children(':not(#inset)').each(function(){
    alert($(this).text());
});

如果你想用一个对象来做:

var selectors = {
    select: '#article',
    exclude: ['#inset', 'p']
};

$(selectors.select).children(':not('+selectors.exclude.join(',')+')').each(function(){
    alert($(this).text());
});

编辑

要获得任何级别的祖先,您可以添加额外的选择器并使用find()。例如。

$('#article').find('li:first, :not(#inset, #inset *)').each(function(){
    alert($(this).text());
});

这样,您将排除 #inset 和所有 #inset 的祖先,但第一个 li 除外。但它不适用于之前的 selectors 对象,因为您排除了一组元素,然后包括了一些被排除的元素。您可以使用对象中的三个元素来做到这一点:

var selectors = {select: ... , exclude: ... , includeFromExcluded: ...};

【讨论】:

  • 谢谢,蒙克。不过,我将如何排除可能处于任何级别的#article 的后代? IIRC,children() 仅将 DOM 向下遍历一层。请参阅我对 meo 的详细回答的评论。
【解决方案3】:

我想您不想通过删除元素来修改原始 HTML,但您只想获取没有插入的文章内容。 这就是为什么我会使用 clone() 来获取文章的副本,然后从中删除插图。

像这样:

$("#article").clone().find("#inset").remove().end().text()
  • $("#article") 选择文章 div,clone 创建一个 复制,
  • find 让孩子们 删除(你也可以使用孩子),
  • remove(),删除选中的插图,
  • end() 返回原来的选择。

最后,我刚刚添加了 text(),正如您所说的那样。

【讨论】:

  • 谢谢,PeterTheNiceGuy - 这看起来可行!现在正在进行一些测试...
【解决方案4】:

除非我遗漏了什么,否则为什么不能选择文章 div 中的所有 &lt;p&gt; 元素?

$("#article p")

如果这是不可接受的,我认为您正在寻找 filter 函数...

$("#article").filter(":not(#inset)")

注意:你可以在 :not() 选择器中有多个选择器。它们只需要用逗号分隔,因此这种方法应该可以满足您的配置需求。

【讨论】:

  • 谢谢,乔希。不过,我无法让它工作 - 我做错了什么吗? (需要 Firebug/Safari 控制台才能看到结果):troy.onespot.com/static/exclusion_selectors.html
  • FWIW,正如我对filter() 的理解,它会将包装集减少为与选择器匹配的集。在这种情况下,它似乎只在#article 上运行,因为它与选择器匹配,所以没有被过滤。我想我需要将filter() 应用于#article 的后代,但是当我在最终/减少的包装集上使用 text() 时,我不确定如何做到这一点而不会导致重复的文本内容。
猜你喜欢
  • 2013-10-11
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 2018-01-17
相关资源
最近更新 更多