WebAssembly : Révolutionnez les Performances de Vos Applications Web
WebAssembly : Révolutionnez les Performances de Vos Applications Web

Interagir avec JavaScript et le DOM

Bienvenue dans cette leçon dédiée à l'interaction avec JavaScript et le Document Object Model (DOM). Dans le cadre de notre cours sur WebAssembly, il est crucial de comprendre comment les performances optimisées de WebAssembly peuvent s'intégrer harmonieusement avec l'interface utilisateur de vos applications web. Si WebAssembly excelle dans les calculs lourds et les logiques complexes, c'est JavaScript, en collaboration avec le DOM, qui reste le chef d'orchestre de l'interface utilisateur, gérant les interactions avec l'utilisateur et mettant à jour visuellement la page.

Cette leçon vous fournira une compréhension approfondie du DOM, des techniques pour y accéder et le manipuler, et expliquera comment JavaScript et WebAssembly peuvent travailler de concert pour créer des applications web puissantes et réactives.

1. Comprendre le DOM (Document Object Model)

Le DOM est une interface de programmation pour les documents HTML et XML. Il représente la structure d'un document sous la forme d'une arborescence d'objets, où chaque nœud de l'arbre correspond à une partie du document (éléments, attributs, texte, etc.).

1.1. Qu'est-ce que le DOM ?

Imaginez une page web non pas comme un simple fichier texte, mais comme une structure hiérarchique d'objets. Le DOM est cette représentation en mémoire. Chaque élément HTML (<div>, <p>, <img>, etc.), chaque attribut (id, class, src), et même le texte à l'intérieur des éléments, est un "nœud" dans cette arborescence.

  • Document: Le nœud racine de l'arbre, représentant la page HTML entière.
  • Éléments: Représentent les balises HTML (e.g., <body>, <h1>, <p>). Ce sont les nœuds les plus courants et les plus manipulés.
  • Attributs: Représentent les attributs des balises HTML (e.g., id="monId", class="maClasse").
  • Texte: Représente le contenu textuel à l'intérieur des éléments.

1.2. Le Rôle du DOM

Le rôle principal du DOM est de permettre aux langages de script, comme JavaScript, d'accéder au contenu du document, de le modifier, de le créer ou de le supprimer, ainsi que d'interagir avec le style (CSS) et les événements. Sans le DOM, JavaScript ne pourrait pas rendre une page interactive ou dynamique. C'est le pont entre votre code et ce que l'utilisateur voit et avec quoi il interagit dans son navigateur.

  • Accès aux éléments : Récupérer des références à des balises HTML spécifiques.
  • Modification de contenu : Changer le texte ou le HTML à l'intérieur d'un élément.
  • Modification de style : Appliquer ou modifier des propriétés CSS.
  • Création/Suppression : Ajouter de nouveaux éléments à la page ou en retirer.
  • Gestion des événements : Répondre aux actions de l'utilisateur (clics, saisies, etc.).

2. Accéder aux Éléments du DOM avec JavaScript

Pour manipuler le DOM, la première étape est de sélectionner les éléments avec lesquels vous souhaitez interagir. L'objet document est le point d'entrée principal pour toutes les opérations DOM.

2.1. Les Méthodes Courantes de Sélection

Voici les méthodes les plus utilisées pour sélectionner des éléments :

  • document.getElementById(id):
    • Sélectionne un seul élément par son attribut id.
    • Retourne l'élément si trouvé, null sinon.
    • Idéal pour les éléments uniques et spécifiques.
  • document.getElementsByClassName(className):
    • Sélectionne tous les éléments ayant une classe spécifique.
    • Retourne une HTMLCollection (similaire à un tableau, mais dynamique).
  • document.getElementsByTagName(tagName):
    • Sélectionne tous les éléments d'un certain type de balise (e.g., 'p', 'div').
    • Retourne une HTMLCollection.
  • document.querySelector(selectors):
    • Sélectionne le premier élément qui correspond au sélecteur CSS spécifié.
    • Utilise la syntaxe des sélecteurs CSS (e.g., '.maClasse', '#monId', 'div p').
    • Retourne un seul élément ou null.
  • document.querySelectorAll(selectors):
    • Sélectionne tous les éléments qui correspondent au sélecteur CSS spécifié.
    • Retourne une NodeList (similaire à un tableau, supporte forEach).

2.2. Exemple Pratique de Sélection

Considérons la structure HTML suivante :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exemple DOM</title>
</head>
<body>
    <div id="conteneurPrincipal" class="conteneur">
        <h1>Bienvenue sur la page d'exemple DOM</h1>
        <p class="texteIntro">Ceci est un paragraphe d'introduction.</p>
        <p class="texteIntro important">Un autre paragraphe important.</p>
        <button id="monBouton">Cliquez-moi !</button>
        <ul>
            <li>Item 1</li>
            <li class="texteIntro">Item 2</li>
            <li>Item 3</li>
        </ul>
    </div>
    <script>
        // Le code JavaScript viendra ici
    </script>
</body>
</html>

Maintenant, voyons comment sélectionner ces éléments avec JavaScript :

// Sélectionner l'élément par son ID
const conteneurPrincipal = document.getElementById('conteneurPrincipal');
console.log('Conteneur Principal (ID):', conteneurPrincipal);

// Sélectionner les éléments par leur classe
const paragraphesIntro = document.getElementsByClassName('texteIntro');
console.log('Paragraphes d\'Introduction (Classe):', paragraphesIntro); // C'est une HTMLCollection

// Sélectionner tous les éléments li (balise)
const listeItems = document.getElementsByTagName('li');
console.log('Tous les éléments de liste (Tag):', listeItems); // C'est une HTMLCollection

// Sélectionner le premier paragraphe avec la classe 'texteIntro' en utilisant querySelector
const premierParaIntro = document.querySelector('.texteIntro');
console.log('Premier Paragraphe Intro (querySelector):', premierParaIntro);

// Sélectionner tous les paragraphes avec la classe 'texteIntro' en utilisant querySelectorAll
const tousLesParasIntro = document.querySelectorAll('.texteIntro');
console.log('Tous les Paragraphes Intro (querySelectorAll):', tousLesParasIntro); // C'est une NodeList

// Sélectionner le bouton par son ID en utilisant querySelector
const monBouton = document.querySelector('#monBouton');
console.log('Mon Bouton (querySelector par ID):', monBouton);

// Sélectionner le deuxième paragraphe qui a la classe 'texteIntro' et 'important'
const paraImportant = document.querySelector('p.texteIntro.important');
console.log('Paragraphe Important (querySelector CSS):', paraImportant);

Explication :

  • getElementById est très direct et renvoie l'élément unique.
  • getElementsByClassName et getElementsByTagName renvoient des HTMLCollections, qui ressemblent à des tableaux mais ne sont pas de vrais tableaux JavaScript. Vous pouvez les itérer avec une boucle for classique ou les convertir en tableau (Array.from(collection)).
  • querySelector et querySelectorAll sont plus flexibles car ils utilisent la syntaxe des sélecteurs CSS. querySelector renvoie le premier match, tandis que querySelectorAll renvoie une NodeList de tous les matchs. Une NodeList peut être parcourue avec forEach.

3. Manipuler le DOM (Création, Modification, Suppression)

Une fois les éléments sélectionnés, vous pouvez les manipuler de diverses manières.

3.1. Modification du Contenu

  • element.textContent: Pour obtenir ou définir le texte brut d'un élément. Sûr contre les attaques XSS car il ne parse pas le HTML.
  • element.innerHTML: Pour obtenir ou définir le contenu HTML d'un élément. Permet d'insérer des balises HTML, mais doit être utilisé avec prudence car il est vulnérable aux attaques XSS si le contenu provient de l'utilisateur.

3.2. Modification des Attributs

Vous pouvez accéder directement aux attributs courants (comme src, href, id, className, value) ou utiliser des méthodes génériques.

  • Accès direct : element.attributeName (e.g., imgElement.src = 'nouvelleImage.jpg').
  • element.setAttribute(name, value): Ajoute ou modifie un attribut.
  • element.getAttribute(name): Récupère la valeur d'un attribut.
  • element.removeAttribute(name): Supprime un attribut.

3.3. Modification du Style (CSS)

  • element.style.propertyName: Accès direct aux propriétés CSS en camelCase (e.g., element.style.backgroundColor = 'blue'). Attention, cela applique des styles inline, qui ont une priorité élevée.
  • element.classList: La méthode préférée pour gérer les styles. Permet de manipuler les classes CSS de manière propre et efficiente.
    • element.classList.add('maClasse')
    • element.classList.remove('maClasse')
    • element.classList.toggle('maClasse') (ajoute si absent, supprime si présent)
    • element.classList.contains('maClasse') (vérifie si la classe est présente)

3.4. Création et Ajout d'Éléments

  • document.createElement(tagName): Crée un nouvel élément HTML (e.g., document.createElement('div')).
  • document.createTextNode(text): Crée un nouveau nœud de texte.
  • parentNode.appendChild(childNode): Ajoute un nœud en tant que dernier enfant d'un parent.
  • parentNode.insertBefore(newNode, referenceNode): Insère un nœud avant un nœud de référence existant.

3.5. Suppression d'Éléments

  • parentNode.removeChild(childNode): Supprime un enfant spécifique d'un élément parent.
  • element.remove(): Une méthode plus moderne et simple pour supprimer directement l'élément lui-même.

3.6. Exemple Pratique de Manipulation

Reprenons notre HTML et manipulons-le :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exemple Manipulation DOM</title>
    <style>
        .highlight {
            background-color: yellow;
            border: 2px solid orange;
            padding: 10px;
        }
        .cache {
            display: none;
        }
    </style>
</head>
<body>
    <div id="conteneur">
        <h1 id="titrePage">Mon Titre Initial</h1>
        <p id="paragrapheDynamique">Contenu initial.</p>
        <img id="monImage" src="placeholder.png" alt="Image de remplacement" width="100">
        <button id="changerContenu">Changer Contenu</button>
        <button id="ajouterElement">Ajouter Élément</button>
        <button id="supprimerDernier">Supprimer Dernier</button>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const titrePage = document.getElementById('titrePage');
            const paragrapheDynamique = document.getElementById('paragrapheDynamique');
            const monImage = document.getElementById('monImage');
            const conteneur = document.getElementById('conteneur');
            const btnChangerContenu = document.getElementById('changerContenu');
            const btnAjouterElement = document.getElementById('ajouterElement');
            const btnSupprimerDernier = document.getElementById('supprimerDernier');

            let compteur = 0;

            // 1. Modification du contenu (textContent et innerHTML)
            btnChangerContenu.addEventListener('click', () => {
                titrePage.textContent = `Titre Modifié ${++compteur}`; // Modifie le texte
                paragrapheDynamique.innerHTML = `Nouveau <em>contenu</em> avec du HTML ! (${compteur})`; // Modifie avec HTML
                
                // 2. Modification des attributs
                if (compteur % 2 === 0) {
                    monImage.src = "https://via.placeholder.com/150/0000FF/FFFFFF?text=WASM"; // Changer la source de l'image
                    monImage.alt = "Image WASM bleue";
                } else {
                    monImage.src = "https://via.placeholder.com/150/FF0000/FFFFFF?text=DOM"; // Revenir à une autre image
                    monImage.alt = "Image DOM rouge";
                }

                // 3. Modification du style via classList
                paragrapheDynamique.classList.toggle('highlight'); // Ajoute/Supprime la classe 'highlight'
            });

            // 4. Création et ajout d'éléments
            btnAjouterElement.addEventListener('click', () => {
                const nouvelDiv = document.createElement('div');
                nouvelDiv.textContent = `Nouvel élément ajouté dynamiquement (${Date.now()})`;
                nouvelDiv.classList.add('highlight'); // Appliquer un style
                nouvelDiv.style.marginTop = '10px'; // Style inline pour l'exemple

                conteneur.appendChild(nouvelDiv); // Ajoute le nouvel élément à la fin du conteneur
            });

            // 5. Suppression d'éléments
            btnSupprimerDernier.addEventListener('click', () => {
                const dernierEnfant = conteneur.lastElementChild;
                if (dernierEnfant && dernierEnfant !== titrePage && dernierEnfant !== paragrapheDynamique && dernierEnfant !== monImage && dernierEnfant !== btnChangerContenu && dernierEnfant !== btnAjouterElement && dernierEnfant !== btnSupprimerDernier) {
                    dernierEnfant.remove(); // Supprime l'élément directement
                    // Ou conteneur.removeChild(dernierEnfant);
                } else {
                    alert("Plus rien à supprimer ou vous essayez de supprimer un élément essentiel !");
                }
            });
        });
    </script>
</body>
</html>

Explication : Ce script montre comment :

  • Le texte d'un <h1> est mis à jour (textContent).
  • Le contenu d'un <p> est mis à jour avec du HTML (innerHTML).
  • L'attribut src et alt d'une <img> sont modifiés.
  • Une classe CSS (highlight) est basculée sur un paragraphe via classList.toggle().
  • Un nouveau <div> est créé (document.createElement), son texte est défini, des classes et styles sont ajoutés, puis il est inséré dans le DOM (appendChild).
  • Le dernier élément enfant (s'il n'est pas un bouton ou un élément initial) est supprimé (remove()).

4. Gérer les Événements du DOM

Les événements sont le moyen par lequel le navigateur nous informe qu'il s'est passé quelque chose, généralement une interaction de l'utilisateur.

4.1. Les Écouteurs d'Événements (addEventListener)

La méthode addEventListener() est la manière préférée et la plus flexible d'attacher des gestionnaires d'événements aux éléments.

Syntaxe : element.addEventListener(eventType, handlerFunction, [options])

  • eventType: Une chaîne de caractères spécifiant le type d'événement à écouter (e.g., 'click', 'mouseover', 'keydown', 'submit', 'load').
  • handlerFunction: La fonction qui sera exécutée lorsque l'événement se produit. Cette fonction reçoit un objet Event comme argument, contenant des informations détaillées sur l'événement.
  • options (optionnel) : Un objet avec des propriétés comme capture (pour la phase de capture), once (pour exécuter le gestionnaire une seule fois), passive (pour améliorer les performances de défilement).

4.2. Types d'Événements Courants

  • Souris : click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout.
  • Clavier : keydown, keyup, keypress.
  • Formulaires : submit (sur le formulaire), change (pour input, select, textarea), focus, blur.
  • Chargement/Fenêtre : load (la page et toutes ses ressources sont chargées), DOMContentLoaded (le DOM est prêt), resize, scroll.

4.3. L'Objet Event

Lorsque la fonction handlerFunction est appelée, elle reçoit un objet Event. Cet objet contient des propriétés utiles :

  • event.target: L'élément sur lequel l'événement s'est produit.
  • event.currentTarget: L'élément sur lequel l'écouteur d'événement est attaché.
  • event.type: Le type d'événement (e.g., "click").
  • event.preventDefault(): Empêche l'action par défaut du navigateur (e.g., empêcher un lien de suivre son href, empêcher un formulaire de se soumettre).
  • event.stopPropagation(): Empêche l'événement de "buller" vers les éléments parents.

4.4. Exemple de Gestion d'Événements

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exemple Événements DOM</title>
    <style>
        #zoneClic {
            width: 200px;
            height: 100px;
            border: 2px solid blue;
            margin-top: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }
        #message {
            margin-top: 10px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <button id="monBouton">Cliquez-moi !</button>
    <div id="zoneClic">Cliquez ici</div>
    <input type="text" id="monInput" placeholder="Tapez quelque chose...">
    <p id="message"></p>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const monBouton = document.getElementById('monBouton');
            const zoneClic = document.getElementById('zoneClic');
            const monInput = document.getElementById('monInput');
            const messagePara = document.getElementById('message');

            // Événement de clic sur un bouton
            monBouton.addEventListener('click', (event) => {
                messagePara.textContent = `Bouton cliqué à ${new Date().toLocaleTimeString()} !`;
                console.log('Type d\'événement:', event.type);
                console.log('Cible de l\'événement:', event.target);
            });

            // Événement de survol de souris
            zoneClic.addEventListener('mouseover', () => {
                zoneClic.style.backgroundColor = 'lightblue';
                messagePara.textContent = 'Souris sur la zone !';
            });

            // Événement de sortie de souris
            zoneClic.addEventListener('mouseout', () => {
                zoneClic.style.backgroundColor = 'white';
                messagePara.textContent = 'Souris hors de la zone.';
            });

            // Événement de saisie dans un champ de texte (input)
            monInput.addEventListener('input', (event) => {
                messagePara.textContent = `Vous avez tapé : "${event.target.value}"`;
            });

            // Événement clavier (keydown)
            monInput.addEventListener('keydown', (event) => {
                if (event.key === 'Enter') {
                    messagePara.textContent = `Touche "Entrée" pressée ! Le champ contient : ${event.target.value}`;
                    event.preventDefault(); // Empêche l'action par défaut (soumission de formulaire si c'était dans un form)
                }
            });

            // Une fois que tout le DOM est chargé
            console.log("Le DOM est entièrement chargé et analysé !");
        });
    </script>
</body>
</html>

Explication : Ce code illustre la capture de différents types d'événements et l'utilisation de l'objet event pour réagir. L'utilisation de DOMContentLoaded assure que le script ne tente d'accéder aux éléments du DOM qu'une fois qu'ils sont disponibles.

5. Le Pont entre WebAssembly et le DOM/JavaScript

C'est ici que la magie opère pour combiner la puissance de calcul de WebAssembly avec la réactivité de l'interface utilisateur JavaScript. WebAssembly et JavaScript sont conçus pour interagir de manière transparente.

5.1. Appels JavaScript depuis WebAssembly (WASM -> JS)

Les modules WebAssembly peuvent importer des fonctions JavaScript pour interagir avec le monde extérieur, y compris le DOM. Cela signifie que votre code WebAssembly, une fois qu'il a effectué un calcul ou atteint un certain état, peut appeler une fonction JavaScript qui, à son tour, manipule le DOM pour afficher les résultats ou mettre à jour l'interface.

  • Cas d'usage : WebAssembly calcule une grande série de données, puis appelle une fonction JS qui prend ces données et les visualise dans un graphique D3.js ou met à jour une table HTML.

5.2. Appels WebAssembly depuis JavaScript (JS -> WASM)

Inversement, JavaScript est responsable du chargement, de la compilation et de l'instanciation des modules WebAssembly. Une fois un module WASM instancié, JavaScript peut appeler les fonctions exportées par ce module. C'est le scénario le plus courant : une action de l'utilisateur (gérée par JS via le DOM) déclenche un calcul lourd dans WebAssembly.

  • Cas d'usage : Un utilisateur clique sur un bouton (événement JS). La fonction JS associée au clic appelle une fonction WebAssembly pour effectuer un traitement d'image complexe. Une fois le calcul terminé par WASM, le contrôle est rendu à JavaScript, qui met à jour l'élément <img> avec l'image traitée.

5.3. Transfert de Données entre JS et WASM

C'est souvent l'aspect le plus délicat de l'interopérabilité. JavaScript et WebAssembly ne partagent pas directement les mêmes types de données de la même manière.

  • Types numériques simples : Les nombres (entiers, flottants) sont transférés facilement.
  • Chaînes de caractères : Les chaînes de caractères nécessitent une conversion. En WASM, elles sont généralement stockées sous forme de tableaux d'octets dans la mémoire linéaire. JavaScript utilise TextEncoder pour convertir des chaînes JS en Uint8Array à passer à WASM, et TextDecoder pour lire des tableaux d'octets de la mémoire WASM en chaînes JS.
  • Objets complexes : Les objets JavaScript (y compris les objets DOM) ne peuvent pas être passés directement à WebAssembly. Vous devez sérialiser les données (par exemple, en JSON) ou passer des références ou des identifiants numériques, puis recréer ou manipuler l'objet du côté JavaScript.

5.4. Exemple Conceptuel d'Interaction JS/WASM/DOM

Imaginez que vous avez un module WebAssembly (calcul.wasm) qui expose une fonction effectuerCalculLourd et une fonction JavaScript afficherResultat(resultat) qui met à jour un <div>.

// index.js (JavaScript)

// 1. Charger et compiler le module WebAssembly
async function chargerWasm() {
    const importObject = {
        env: {
            // Fonction JavaScript importée par WASM pour afficher le résultat
            afficherResultatDansDOM: (result) => {
                const resultatDiv = document.getElementById('resultatWasm');
                if (resultatDiv) {
                    resultatDiv.textContent = `Résultat du calcul WASM : ${result}`;
                    console.log(`WASM a appelé JS pour afficher : ${result}`);
                }
            }
        }
    };

    const response = await fetch('calcul.wasm');
    const bytes = await response.arrayBuffer();
    const { instance } = await WebAssembly.instantiate(bytes, importObject);

    // Retourne les fonctions exportées par le module WASM
    return instance.exports;
}

document.addEventListener('DOMContentLoaded', async () => {
    const wasmExports = await chargerWasm();
    const btnDemarrerCalcul = document.getElementById('demarrerCalcul');
    const resultatDiv = document.getElementById('resultatWasm');

    if (!wasmExports || !wasmExports.effectuerCalculLourd) {
        resultatDiv.textContent = "Erreur: Module WebAssembly non chargé ou fonction manquante.";
        return;
    }

    // 2. JS écoute un événement DOM (clic bouton)
    btnDemarrerCalcul.addEventListener('click', () => {
        resultatDiv.textContent = "Calcul en cours par WebAssembly...";
        console.log("JS appelle la fonction WASM...");
        
        // 3. JS appelle une fonction exportée par WASM
        const valeurInitiale = 10000000;
        wasmExports.effectuerCalculLourd(valeurInitiale); // WASM effectuera le calcul et appellera la fonction JS pour afficher

        // Note: Si la fonction WASM retournait un résultat, on pourrait le traiter ici:
        // const resultatRetourne = wasmExports.effectuerCalculLourd(valeurInitiale);
        // resultatDiv.textContent = `Calcul synchrone WASM: ${resultatRetourne}`;
    });
});
<!-- index.html -->
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Interaction WASM-JS-DOM</title>
</head>
<body>
    <h1>Démo WebAssembly et DOM</h1>
    <button id="demarrerCalcul">Démarrer Calcul Lourd (WASM)</button>
    <div id="resultatWasm" style="margin-top: 20px; font-size: 1.2em; color: green;">
        Cliquez sur le bouton pour démarrer un calcul WASM.
    </div>

    <script src="index.js"></script>
</body>
</html>
;; calcul.wat (WebAssembly Text Format, pour illustrer le concept)
;; Compilez ceci en calcul.wasm avec un outil comme `wat2wasm` ou utilisez un langage haut niveau.

(module
  (import "env" "afficherResultatDansDOM" (func $afficher_resultat (param i32)))

  (func (export "effectuerCalculLourd") (param $valeur_initiale i32)
    (local $i i32)
    (local $result i32)

    ;; Initialiser le résultat
    (set_local $result (get_local $valeur_initiale))

    ;; Boucle de calcul lourd (exemple simple: addition répétée)
    (loop $boucle
      (set_local $i (i32.add (get_local $i) (i32.const 1)))
      (set_local $result (i32.add (get_local $result) (i32.const 1)))
      (br_if $boucle (i32.lt_s (get_local $i) (i32.const 100000000))) ;; Boucle 100 millions de fois
    )

    ;; Appeler la fonction JavaScript pour afficher le résultat
    (call $afficher_resultat (get_local $result))
  )
)

Explication :

  • Le fichier index.js charge le module calcul.wasm.
  • Il définit un importObject qui contient la fonction JavaScript afficherResultatDansDOM. Cette fonction est "visible" par le module WASM sous le nom env.afficherResultatDansDOM.
  • Lorsqu'un utilisateur clique sur le bouton, la fonction JS attache au bouton appelle wasmExports.effectuerCalculLourd.
  • effectuerCalculLourd (dans le WASM) exécute un calcul intensif.
  • Une fois le calcul terminé, la fonction WASM call $afficher_resultat est exécutée, ce qui fait appel à la fonction JavaScript afficherResultatDansDOM.
  • Enfin, la fonction JavaScript met à jour le div dans le DOM avec le résultat, bouclant ainsi le cycle d'interaction.

Cette architecture permet de décharger les calculs lourds vers WebAssembly tout en conservant la flexibilité et la facilité d'interaction de JavaScript avec le DOM pour la partie interface utilisateur.

Conclusion

L'interaction avec JavaScript et le DOM est une compétence fondamentale pour tout développeur web, et elle reste absolument cruciale même dans un écosystème intégrant WebAssembly.

Nous avons exploré :

  • La nature du DOM en tant que représentation arborescente de votre page HTML.
  • Les diverses méthodes JavaScript pour accéder aux éléments du DOM (getElementById, querySelector, etc.).
  • Les techniques pour manipuler le DOM : modifier le contenu (textContent, innerHTML), les attributs (setAttribute), le style (classList), créer et supprimer des éléments.
  • La gestion des événements DOM via addEventListener pour rendre vos applications interactives.
  • Enfin, nous avons mis en lumière le pont essentiel entre WebAssembly et le DOM/JavaScript, où WebAssembly prend en charge les calculs lourds, et JavaScript orchestre l'interface utilisateur en manipulant le DOM et en agissant comme un relai entre l'utilisateur et le moteur WASM.

En comprenant et en maîtrisant ces interactions, vous êtes bien équipé pour bâtir des applications web robustes et performantes, où WebAssembly et JavaScript collaborent harmonieusement pour offrir une expérience utilisateur exceptionnelle.