Вы можете выбрать всех .MyClass
потомков, затем .filter
коллекции по тому, есть ли у текущего элемента, который повторяется, предок #excludedElement
с .closest
:
const classes = [...container.querySelectorAll('.MyClass')]
.filter(span => !span.closest('#excludedElement'));
for (const span of classes) {
span.style.backgroundColor = 'yellow';
}
<div id="container">
<div class="A">
<div id="excludedElement">
<p>
<span class="MyClass">1</span>
<span class="MyClass">2</span>
<span class="MyClass">3</span>
</p>
</div>
</div>
<div class="B">
<p>
<span class="MyClass">4</span>
<span class="MyClass">5</span>
<span class="MyClass">6</span>
</p>
</div>
</div>
Если вы заранее не знаете точную структуру потомков #container
, я не думаю, что есть элегантный способ сделать это с одиночная строка запроса; :not
принимает только простые селекторы.
Просто для информационных целей глупый и повторяющийся метод, который вы не должны использовать, будет использовать строку запроса:
:scope > .MyClass,
:scope > *:not(#excludedElement) > .MyClass,
:scope > *:not(#excludedElement) > *:not(#excludedElement) > .MyClass
...
const selector = `
:scope > .MyClass,
:scope > *:not(#excludedElement) > .MyClass,
:scope > *:not(#excludedElement) > *:not(#excludedElement) > .MyClass
`;
const classes = container.querySelectorAll(selector);
for (const span of classes) {
span.style.backgroundColor = 'yellow';
}
<div id="container">
<div class="A">
<div id="excludedElement">
<p>
<span class="MyClass">1</span>
<span class="MyClass">2</span>
<span class="MyClass">3</span>
</p>
</div>
</div>
<div class="B">
<p>
<span class="MyClass">4</span>
<span class="MyClass">5</span>
<span class="MyClass">6</span>
</p>
</div>
</div>