Maison >interface Web >js tutoriel >TreeWalker : un guide pratique de la traversée du DOM

TreeWalker : un guide pratique de la traversée du DOM

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-23 01:02:11690parcourir

Récemment, j'ai commencé à travailler sur une nouvelle extension Chrome pendant mon temps libre et dans la recherche sur la façon de gérer certaines fonctionnalités, j'ai commencé à découvrir de plus en plus de fonctionnalités dont JS dispose pour gérer le DOM du page.

Étant donné qu'un nombre écrasant de personnes utilisant JS l'utilisent uniquement via un framework, cela constituerait un sujet intéressant pour une série d'articles courts permettant aux gens d'en apprendre un peu plus sur les technologies sous-jacentes sur lesquelles les frameworks sur lesquels ils s'appuient sont utilise réellement.

Nous sommes tous passés par là : vous devez trouver des éléments spécifiques dans le DOM, mais querySelector et getElementsBy* ne suffisent pas vraiment. Peut-être avez-vous besoin de trouver tous les nœuds de texte contenant une phrase spécifique, ou souhaitez-vous parcourir des éléments correspondant à certaines conditions tout en en ignorant d'autres. Entrez TreeWalker - une API de traversée DOM puissante mais souvent négligée.

Qu’est-ce que TreeWalker ?

TreeWalker est une interface DOM qui vous permet de parcourir et de filtrer efficacement les nœuds DOM. Considérez-le comme une alternative plus puissante et plus flexible aux méthodes telles que querySelector. Alors que querySelector vous donne des éléments correspondant à un sélecteur CSS, TreeWalker vous permet :

  • Naviguez dans l'arborescence DOM dans n'importe quelle direction (avant, arrière, haut, bas)
  • Filtrer les nœuds en fonction de conditions personnalisées
  • Ignorer entièrement certaines parties de l'arbre
  • Accéder directement aux nœuds de texte (quelque chose que querySelector ne peut pas faire)

Créer un TreeWalker

Commençons par un exemple basique :

const walker = document.createTreeWalker(
    document.body, // Root node to start traversal
    NodeFilter.SHOW_TEXT, // Only show text nodes
    {
        acceptNode: function(node) {
            // Only accept text nodes that aren't empty
            return node.textContent.trim().length > 0
                ? NodeFilter.FILTER_ACCEPT
                : NodeFilter.FILTER_REJECT;
        }
    }
);

Les trois paramètres sont :

  1. Nœud racine — par où commencer la traversée
  2. Quels types de nœuds afficher (texte, éléments, commentaires, etc.)
  3. Une fonction de filtre qui décide quels nœuds accepter ou rejeter

Exemples du monde réel

1. Rechercher et remplacer du texte

Voici quelque chose que vous utiliserez réellement : rechercher et remplacer du texte tout en préservant la structure HTML.

function replaceText(root, search, replace) {
    const walker = document.createTreeWalker(
        root,
        NodeFilter.SHOW_TEXT,
        {
            acceptNode: function(node) {
                return node.textContent.includes(search)
                    ? NodeFilter.FILTER_ACCEPT
                    : NodeFilter.FILTER_REJECT;
            }
        }
    );

    let node;
    while (node = walker.nextNode()) {
        node.textContent = node.textContent.replace(search, replace);
    }
}

// Usage
replaceText(document.body, 'old text', 'new text');

C'est beaucoup plus efficace que d'utiliser innerHTML et ne brisera pas les écouteurs d'événements ni ne formera de valeurs d'entrée.

2. Requête DOM personnalisée

Besoin de trouver des éléments correspondant à des conditions complexes ? TreeWalker a ce qu'il vous faut. Construisons quelque chose de plus complexe : disons que vous devez trouver tous les éléments éléments contenant du texte spécifique, mais uniquement s'ils se trouvent à l'intérieur de

éléments avec une certaine classe et ignorez ceux qui se trouvent à l'intérieur de éléments :

function findElementsByComplexCondition(root, config) {
    const results = [];
    const walker = document.createTreeWalker(
        root,
        NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
        {
            acceptNode: function(node) {
                // Skip nodes we don't care about early
                if (node.nodeType === Node.ELEMENT_NODE &&
                    node.tagName === 'BUTTON') {
                    return NodeFilter.FILTER_REJECT; // Skip button and its contents
                }

                // Check for matching span elements
                if (node.nodeType === Node.ELEMENT_NODE &&
                    node.tagName === 'SPAN') {
                    // Check if parent is a div with required class
                    const parent = node.parentElement;
                    if (!parent ||
                        parent.tagName !== 'DIV' ||
                        !parent.classList.contains(config.parentClass)) {
                        return NodeFilter.FILTER_SKIP;
                    }

                    // Check if span contains the required text
                    const text = node.textContent?.toLowerCase() || '';
                    if (!text.includes(config.searchText.toLowerCase())) {
                        return NodeFilter.FILTER_SKIP;
                    }

                    return NodeFilter.FILTER_ACCEPT;
                }

                return NodeFilter.FILTER_SKIP;
            }
        }
    );

    let node;
    while (node = walker.nextNode()) {
        results.push(node);
    }
    return results;
}

Cela correspondrait :

✅ Correspondra :

<div>



<p>❌ Won't match all of the following:<br>
</p>

<pre class="brush:php;toolbar:false"><div>



<p>[Rest of code examples...]</p>

<h2>
  
  
  The Swiss Army Knife of DOM Traversal
</h2>

<p>TreeWalker isn't limited to forward traversal. You can move in any direction:<br>
</p>

<pre class="brush:php;toolbar:false">// Move to next node
walker.nextNode();

// Move to previous node
walker.previousNode();

// Move to first child
walker.firstChild();

// Move to last child
walker.lastChild();

// Move to parent
walker.parentNode();

Quand devriez-vous utiliser TreeWalker ?

TreeWalker brille quand :

  1. Vous devez trouver des nœuds de texte (querySelector ne peut pas faire cela)
  2. Vous avez des exigences de filtrage complexes
  3. Vous devez parcourir le DOM dans un ordre spécifique
  4. Les performances comptent (TreeWalker est généralement plus rapide que la traversée récursive du DOM)

Prise en charge du script dactylographié

Bonne nouvelle pour les utilisateurs de TypeScript : les types sont intégrés :

const walker = document.createTreeWalker(
    document.body, // Root node to start traversal
    NodeFilter.SHOW_TEXT, // Only show text nodes
    {
        acceptNode: function(node) {
            // Only accept text nodes that aren't empty
            return node.textContent.trim().length > 0
                ? NodeFilter.FILTER_ACCEPT
                : NodeFilter.FILTER_REJECT;
        }
    }
);

Pensées finales

TreeWalker est l'une de ces API que, une fois que vous en aurez connaissance, vous vous retrouverez à utiliser plus souvent que vous ne le pensez. Il est particulièrement utile pour créer des outils d'accessibilité, des systèmes de gestion de contenu ou toute application nécessitant d'analyser ou de modifier le contenu DOM par programme.

Bien que cela puisse paraître complexe au premier abord, la puissance et la flexibilité de TreeWalker valent la peine de l'ajouter à votre boîte à outils. La prochaine fois que vous vous retrouverez à écrire une fonction de traversée récursive du DOM, demandez-vous si TreeWalker pourrait être une meilleure solution.

P.S. Si vous êtes arrivé jusqu'ici, voici un conseil de pro : combinez TreeWalker avec MutationObserver pour créer de puissants outils de surveillance DOM. Mais c'est un sujet pour un autre article... ?


Si vous avez trouvé cet article utile, n'hésitez pas à aimer et à suivre pour plus de trucs et astuces JavaScript.

Photo de couverture par Branko Stancevic sur Unsplash

TreeWalker: A Practical Guide to DOM Traversal

Photo de couverture par Branko Stancevic sur Unsplash
Photo de chat par Jan Gustavsson sur Unsplash

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn