Лучший способ понять эту проблему состоит в том, что структура HTML - это структура данных Tree (на самом деле это DAG, если вы хотите sh продолжить исследование).
Эти проблемы являются частью структуры данных CS101 (и как пройти / поиск). Предоставлено решение DFS.
Однако для решения этой проблемы необходимо учитывать recursion
.
т.е. с учетом древовидной структуры следующего
| root
|
|- leaf node
|- node with children
|- leaf node
Итак, идея в том, где вы сначала найдете узел root. Здесь вы ищете document.querySelector('ul')
, затем вы будете искать листовые узлы в root ul
. здесь вы будете делать что-то вроде document.querySelector('ul > li')
. это даст вам существующие дочерние узлы от root.
оттуда - вам нужно будет переключить родительский элемент с дочерним, чтобы выполнить действие рекурсивно.
я предоставлю пример ниже:
// helper fn
const findChildren = el => [...el.children].filter(el => el.tagName === "LI")
const root = document.querySelector("ul");
const children = findChildren(root);
const traverse = (baseNode, children, iter = 1) => {
// process baseNode here with iter here
baseNode.classList.add(`list-${iter.toString()}`)
for (child of children) {
child.classList.add(`child-${iter.toString()}`)
let hasGranChild = [...child.children].filter(el => el.tagName === "UL").length
if (hasGranChild) {
let newChild = [...child.children].find(el => el.tagName === "UL");
const granChildren = findChildren(newChild)
traverse(newChild, granChildren, iter + 1)
}
}
}
traverse(root, children)
<ul>
<li><a>Title level 1</a></li>
<li><a>Title level 1</a>
<ul>
<li><a>Title level 2</a>
<ul>
<li><a>Title level 3</a></li>
<li><a>Title level 3</a></li>
</ul>
</li>
<li><a>Title level 2</a>
<ul>
<li><a>Title level 3</a></li>
<li><a>Title level 3</a></li>
<li><a>Title level 3</a></li>
</ul>
</li>
</ul>
</li>
<li><a>Title level 1</a>
<ul>
<li><a>Title level 2</a></li>
</ul>
</li>
<li><a>Title level 1</a></li>
<li><a>Title level 1</a>
<ul>
<li><a>Title level 2</a></li>
</ul>
</li>
</ul>
Результат
<ul class="list-1">
<li class="child-1"><a>Title level 1</a></li>
<li class="child-1"><a>Title level 1</a>
<ul class="list-2">
<li class="child-2"><a>Title level 2</a>
<ul class="list-3">
<li class="child-3"><a>Title level 3</a></li>
<li class="child-3"><a>Title level 3</a></li>
</ul>
</li>
<li class="child-2"><a>Title level 2</a>
<ul class="list-3">
<li class="child-3"><a>Title level 3</a></li>
<li class="child-3"><a>Title level 3</a></li>
<li class="child-3"><a>Title level 3</a></li>
</ul>
</li>
</ul>
</li>
<li class="child-1"><a>Title level 1</a>
<ul class="list-2">
<li class="child-2"><a>Title level 2</a></li>
</ul>
</li>
<li class="child-1"><a>Title level 1</a></li>
<li class="child-1"><a>Title level 1</a>
<ul class="list-2">
<li class="child-2"><a>Title level 2</a></li>
</ul>
</li>
</ul>
в рамках рекурсивного характера функции вы можете перейти на текущий «уровень» "внутри аргументов функции. Задав начальный iter = 1
, вам все равно, насколько "глубоко" уходит дерево. И так как вы используете CSS селектор прямого потомка (то есть el1 > el2
), который вы спрашиваете, можете ли вы дать мне прямых потомков el1 which are el2
?