4

我正在尝试找出以下标记的选择器。我想要所有节点,除了包含 blockquote 的节点。将<blockquote>始终是 a 的直接子代,<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()器。这是失败尝试的小提琴

我目前不是,也不能使用 jQuery。

4

1 回答 1

4

你不能在本地做到这一点。在任何当前的选择器规范中,都无法通过子元素过滤元素。(不过,这可能会出现在未来的选择器规范中。)

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

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');
于 2013-11-11T16:13:26.510 回答