Дивовижний світ веброзробки
2.91K subscribers
83 photos
7 videos
1 file
183 links
Дивовижний світ веброзробки — тепер і в твоєму телеграмі. Анонси відео з YouTube-каналу «Сергій Бабіч та Дивовижний світ веброзробки», стріми, авторські статті та цікаві знахідки.

youtube.com/@babichweb

Реклами та інтеграції обговоримо
Download Telegram
#dom_api
Не буду стверджувати, що обхід DOM-дерева є повсякденною рутиною, але іноді така потреба постає, і тоді перед нами постає вибір: або ми це робимо рекурсивно і вручну, або нормально. Питання лише в тому, що про нормальний спосіб мало хто знає. От я знаю про нього вже кілька років, а на практиці довелося використати буквально днями.

Мова йтиме про TreeWalker. Як я вже казав, про його існування я знав давно, але прикладних задач для нього не мав. Аж тут сталося цікаве співпадіння: по-перше, Дмитро Тарасенко розповідав про свою маленьку бібліотечку для скрапінгу на React+ Fwdays'25, чим нагадав мені про існування TreeWalker взагалі, і, по-друге, днями я брав участь в досить цікавому лайвкодингу, де мені довелося в прямому етері, так би мовити, вперше з цим API попрацювати. Тож в двох словах розповім про нього.

Якщо коротко, то TreeWalker дозволяє послідовно обходити дерево вузлів DOM. Але є кілька дуже важливих нюансів. Перше, можна фільтрувати тип вузлів за власними правилами. Друге — він не обмежує нас в напрямку руху обходу, на відміну від рекурсії.

Так-так, він завжди памʼятає поточну ноду і дозволяє рухатися як вверх-вниз, так і по сусідах, а не лише вперед і вниз.

Це робить його дуже гнучким інструментом для швидкого обходу дерева, бо з ним можна не лише мандрувати в будь-якому напрямку, а зупинити обхід у будь-який момент та потім, згодом, відновити його з того ж місця.

Виглядає ініціалізація приблизно так:
const walker = document.createTreeWalker(
// корінь обходу
document.body,
// тип вузлів, які враховуємо
NodeFilter.SHOW_ELEMENT,
// кастомний фільтр
{
acceptNode(node) {
return node.tagName === 'P'
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_SKIP;
}
}
);


і потім перебираємо як нам до вподоби:
let node = walker.currentNode;

while (node) {
console.log(node.tagName);
node = walker.nextNode();
}


TreeWalker не є альтернативою NodeIterator, а радше його "прокачаною" версією. NodeIterator також послідовно рухається деревом, але строго вперед або назад, більше нагадуючи ручний рекурсивний підхід, але з можливістю "перемотки".

З вас вподобайка і поширення, навіть якщо досі ні чорта не зрозуміло.

Найчастіше TreeWalker використовується тоді, коли потрібний саме обхід дерева, а не просто querySelectorAll. Наприклад, коли нам потрібно знайти фрагменти дерева, що відповідає певній структурі, чи елемент за певними правилами, які не можна описати селектором. І так, на відміну від querySelector*, він дозволяє обходити саме вузли, не лише елементи.

Звичайно ж, без підводних каменів нікуди. По-перше, TreeWalker не бачить Shadow DOM. Ну, на те він і Shadow, звичайно.

По-друге, фільтр acceptNode викликається для кожного вузла, тому при великому DOM варто уникати зайвих перевірок.

І, по-третє, TreeWalker працює з живим DOM, тому, певно, варто уникати операцій з деревом під час обходу, інакше він може несподівано затягнутись.

TreeWalker — це маленький, але дуже потужний API. Він дозволяє пройтись DOM не "згори донизу", а саме так, як тобі зручно, дозволяючи самотужки задавати правила, перестрибувати від сусідів до сусідів, від батьківських вузлів до дочірніх і усе це — з кнопками "play", "pause", "rewind" і "forward" прямо з коробки. Така собі міжпросторова рекурсія з подорожами в часі (так, я полюбляю безглузді метафори).

Я навіть не буду питати, чи ви вже використовували його в проді, а якщо використовували — отримайте від мене щиру заздрість, що працюєте з такими цікавими задачами )

Що почитати:
📖 MDN: TreeWalker
📖 MDN: NodeIterator

Що почитати душнілам:
📖 W3C: Document Object Traversal
📖 WHATWG: TreeWalker

P.S. Товариство, детектори дронів самі себе не куплять, запрошую закинути пару гривень на збір.
🔥6624👍12🤔1