Select css 两个元素之间的兄弟姐妹

Select css siblings between two elements

我正在查看的 html 看起来像这样:

document.querySelectorAll('h4#unique_id  ~ h5 ~p +p +h5').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

我想获取所有 h5 元素,如果可能,还想获取 p 元素。

到目前为止我有 document.querySelectorAll('h4#unique_id ~ h5 ~p +p +h5'),但是它错过了我想要的第一个 h5 并且抓住了我不想要的最后一个。当我找到另一个 h4.

时,我无法弄清楚兄弟选择器或如何使用 :not 或类似的方法来停止

这道题 relies on jquery which I don't have access to, and 需要知道元素的数量和位置,而我不知道。

仅使用 css 个选择器是否可行?

好的,您可以混合使用兄弟选择器而不是:

选择器是:

#unique_id~p:not(#unique_id~h4~p) /* any p following the unique id but not a p following another h4 after the unique id */

然后你为你的 h5s 重复这个选择器,结果是:

document.querySelectorAll('#unique_id~p:not(#unique_id~h4~p),#unique_id~h5:not(#unique_id~h4~h5)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

根据您的编辑 - 不要在第一个 h5 之前包含 p(选择器根据 Alohci 的评论略作修改):

document.querySelectorAll('#unique_id~:is(h5, h5~p):not(#unique_id ~ h4 ~ *)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

有趣的问题。如果我正确理解你的问题,你想记录所有不包含 some text I don't wanth5 元素的元素。

如果您有父元素,您可以使用 > 到 select 或与父元素结合使用 select 它的所有子元素 *-select或.

您可以对一个语句应用多个 :not()-selector。下面我只是 selected 所有 ph4 元素前面有 h4#randome_id_234353 元素,像这样:

document.querySelectorAll('.container > *:not(h4#randome_id_234353 ~ p):not(h4#randome_id_234353 ~ h5):not(h4)').forEach(title => console.log(title))
<body>
<div class="container">
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</div>
</body>

如果您没有容器,您可以使用相同的逻辑来 log 所有 先于 h4#randome_id_234353.

document.querySelectorAll('h4#unique_id ~ *:not(h4#randome_id_234353 ~ *):not(h4#randome_id_234353)').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

只有少数数组方法与 array-like 对象一起工作,因此我经常发现将 NodeList(这是一个 可迭代对象,array-like object 但是,至关重要的是, 不是 一个 array) 到一个 array,这样我就可以做 更多用它做事

在这种情况下,通过将 NodeList 变成 array 我可以使用 javascript 方法 .filter() 这正是我需要从合集结束。


NodeList 变成 array:

我怎样才能把这个static NodeList:

let myClassElements = document.querySelectorAll('.myclass');

变成 array?

通过将 spread syntax (...) 与 array literal ([]) 组合:

let myClassElements = [... document.querySelectorAll('.myclass')];

在此基础上,我可以创建一个 array 我需要的所有元素(加上一些不必要的元素):

[...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')]

还有另一个所有不必要元素的数组:

[...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')]

然后我可以.filter()从前者中分离出后者:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));

工作示例:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>