【问题标题】:Query selector for nodes not containing blockquote查询不包含块引用的节点的选择器
【发布时间】:2013-11-23 12:17:04
【问题描述】:

我正在尝试找出以下标记的选择器。我想要所有节点,除了包含块引用的节点<blockquote> 将始终是 <div> 的直接子代,<div> 将是 <body> 标记的直接子代。

示例 HTML:

<ul>
    <!-- Lots of HTML -->
</ul>
<div>
    <p>
        <!-- Lots of other HTML -->
    </p>
</div>
<div>
    <blockquote>Some text I don't care about</blockquote>
</div>

预期结果:

<ul><!-- Lots of HTML --></ul>
<div><p><!-- Lots of other HTML --></p></div>

尝试的选择器:

document.querySelectorAll("body > :not(div > blockquote)")

我尝试了上述方法,但无法在 :not() 选择器中放置直接子选择器。尝试失败的Here is a fiddle

我目前没有也不能使用 jQuery。

【问题讨论】:

  • 兄弟姐妹是彼此并存的元素,在您的情况下,&lt;ul&gt; 和跟随它的两个 &lt;div&gt;s 是兄弟姐妹。 &lt;blockquote&gt; 是其&lt;div&gt;child,而&lt;div&gt; 又是&lt;body&gt;child&gt; 是子选择器。 (直接兄弟选择器是+。)
  • @BoltClock 呵呵,太晚了!会更新

标签: javascript css-selectors selectors-api


【解决方案1】:

您无法在本地执行此操作。在任何当前的选择器规范中,都无法通过子元素过滤元素。 (不过,这可能会出现在未来的选择器规范中。)

因此,您需要自己进行过滤。这并不是特别困难。一种方法是选择所有相关元素,然后过滤掉不需要的元素:

Array.prototype.slice.call(document.querySelectorAll("body > *"))
    .filter(function(el) {
        return !el.querySelector(':scope > blockquote');
    })

(jsFiddle)

这会将所选内容变成一个数组,然后使用Array#filter 方法删除所有包含blockquote 元素的内容。

显然,这比原生选择器的性能要差得多,但它是在当前 JS 中做你想做的事情的唯一方法。

正如 BoltClock 正确指出的那样,:scope 还不是官方标准。 Chrome确实支持这一事实让我陷入了一种虚假的安全感:其他浏览器目前还不支持。如果您想在任何级别排除包含 blockquote 元素的任何顶级元素,最好的方法是:

return !el.querySelector('blockquote');

【讨论】:

  • @tenbits 我不确定这是否会对 OP 产生影响,但是是的,这就是问题的准确措辞。所以...更新了答案。
  • 在您发表评论之前删除了我的评论)因为您编辑的解决方案使用 ':scope' 效果更好;)
  • 使用:scope 可能还为时过早。 (请注意,:scope 来自与主题指示器(选择器 4)相同的规范,但考虑到它的吸引力,浏览器​​可能会首先实现 :scope。)
  • 更新的很完美。我可能需要保留嵌套的&lt;blockquote&gt; 元素。我在这里针对的是最新版本的 Chrome,所以 :scope 应该没问题。
猜你喜欢
  • 1970-01-01
  • 2015-05-08
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多