6 Punkte von GN⁺ 2023-11-07 | 1 Kommentare | Auf WhatsApp teilen
  • Der Beitrag behandelt die umfassende Beherrschung der Manipulation des Document Object Model (DOM) mit Vanilla JavaScript.
  • Er betont, wie wichtig es ist, die Browser-DOM-API für die Webentwicklung zu verstehen, trotz der Nutzung moderner Tools wie Angular, VueJS, React, Solid und Svelte.
  • Der Autor stellt eine Sammlung von Materialien bereit, darunter grundlegende Browser-APIs, leicht verständliche Beispiele, Live-Demos, Tipps und Best Practices, praktische Anwendungsfälle sowie Kompatibilität mit modernen Browsern und Internet Explorer.
  • Diese Materialien sind in drei Stufen unterteilt: Grundlagen, Mittelstufe und Fortgeschrittene.
  • Zur Grundstufe gehören Aufgaben wie das dynamische Ändern des Favicons entsprechend der bevorzugten Farbgebung des Nutzers, das Berechnen der Lesezeit einer Webseite und das dynamische Aktualisieren von CSS-Root-Variablen.
  • Zur Mittelstufe gehören Aufgaben wie das Entfernen von Einrückungen in einem Textbereich mit der Tastenkombination Shift+Tab, das Wechseln in den Vollbildmodus und das Erstellen eines Spin-Inputs.
  • Zur fortgeschrittenen Stufe gehören Aufgaben wie das Erstellen eines benutzerdefinierten Cursors, das Bereinigen von HTML-Strings und das Erstellen einer benutzerdefinierten Scrollbar.
  • Der Autor gibt außerdem Tipps, etwa wie man Layout-Verschiebungen beim Öffnen eines Modals vermeidet oder wie man das Begrenzungsrechteck von Textknoten erhält.
  • Der Beitrag endet mit einer Einladung, den Newsletter des Autors zu Frontend-Tech-Inhalten zu abonnieren.

1 Kommentare

 
GN⁺ 2023-11-07
Hacker-News-Kommentare
  • Die Liste der Beispiele ist großartig, und schon beim Überfliegen einiger davon ist die Sorgfalt und Detailtiefe erstaunlich
    Wenn man von Plattformen wie React zu kleineren, minimaleren Implementierungen wechselt, hänge ich oft daran fest, wie man komplexe Muster mit Standard-JS umsetzen soll, aber wenn man sich den Code dann ansieht, denkt man manchmal: „Das ist viel einfacher, als Unmengen von Properties an eine riesige Bibliothek zu übergeben.“

    • Nach 3–4 Major-Updates von RiotJS hatte ich eine ähnliche Erkenntnis
      Auch minimale JS-Frameworks werden leicht zu Monstern aus Hooks, Events und zusammengeflickten Side Effects, wenn sich scheinbar harmlose Feature-Requests ansammeln
      Heutzutage nutze ich nicht einmal mehr jQuery, und Dinge wie ES-Module verwende ich zum Strukturieren des Codes, aber dafür muss ich nicht extra npm-Befehle ausführen. Das ist nichts, was man als Vendor-Paket hereinziehen müsste, sondern ein globaler Browser-Standard
      In letzter Zeit lese ich MDN wie eine Bibel. Wenn man sich daran hält, kommt man fast bis ans Ziel, und Frameworks stehen einem ab einem gewissen Punkt eher im Weg. Vor 5 Jahren war das noch nicht in diesem Maß so, aber die Browser-APIs haben sich schnell auf leistungsfähige und konsistente Grundbausteine wie Module, Flexbox und Grid eingependelt
    • Die Beispiele im Original stehen nicht wirklich in Konkurrenz zu Web-Client-Frameworks. Die typischen Probleme, die Frameworks lösen, sind State Management und das Aktualisieren der UI bei Zustandsänderungen
      Zum Beispiel ist der Großteil der Beispiele im Original Code, den man selbst mit React noch direkt schreiben müsste
  • Als Side Project baue ich gerade etwas noch namenloses wie ein „vim für Webdesigner“. Wie bei Webflow erstellt man Websites oder Komponenten im Browser, aber alles wird über eine Befehlssprache gesteuert
    Am Anfang hatte ich mir fest vorgenommen, es ohne Framework zu machen. Ich mache diesen Job seit 2009 und benutze JS schon lange seit vor meiner Framework-Zeit, also dachte ich, dass die native DOM-API völlig ausreicht
    Aber das Verschieben von Daten in und aus dem DOM war so langweilig und fehleranfällig, dass ich am Ende aus Gründen der geistigen Gesundheit doch begonnen habe, ein Mini-Framework selbst zu verwenden. Da fiel mir wieder ein, warum ich überhaupt irgendwann Frameworks eingesetzt hatte. Am Ende verwendet man in irgendeiner Form immer ein Framework; der Unterschied ist nur, ob es ein selbst gebautes maßgeschneidertes ist oder ein von der Community gemachter Industriestandard
    Für Websites mit wenig Interaktion ist natives DOM gut, und die meisten Sites, die React verwenden, bräuchten es wahrscheinlich gar nicht. Aber sobald ein Produkt auch nur etwas Nuance oder Komplexität hat, würde ich lieber ein Framework nutzen und mir die Umständlichkeit sparen. Ich bin schließlich zu Svelte gewechselt und deutlich zufriedener damit

    • Bei ultraminimalen Projekten landet man am Ende doch wieder dabei, die Hälfte von jquery oder lodash neu zu implementieren. Es ist viel einfacher, eine gute Bibliothek wie ramda zu finden, die sich gut tree-shaken lässt, und sie sparsam einzusetzen
    • „Wenn man kein Framework auswählt, baut man sich selbst eines“ trifft es ziemlich genau
    • Hier geht es um das Erstellen einer Applikation, daher kann man schon anhand der Beschreibung vermuten, dass es besser ist, die DOM-Interaktion zu kapseln
      Für Websites, die Interaktion brauchen, kann DOM-Manipulation trotzdem die bessere Wahl sein, weil man damit eine grundlegendere und allgemeinere Technik nutzt, der Build-Prozess leichtgewichtig oder gar nicht vorhanden ist, die Ausführung schnell ist und alles explizit bleibt
      Natürlich gibt es viel Grauzone, aber dieser Fall fällt genau in die Kategorie, in der ein Framework im Vorteil ist
    • SvelteKit ist inzwischen stark auf SSR ausgerichtet, und Svelte selbst hat keinen eingebauten Client-Side-Router. Ich wollte Svelte für eine CSR-Single-Page-App einsetzen, habe es dann aber aufgegeben
  • Schon value.startsWith('javascript:') allein erzeugt eine Schwachstelle. Vor der URL kann beliebiger Whitespace stehen, daher braucht man mindestens value.trim().startsWith('javascript:')
    Trotzdem halte ich eine Allowlist für besser als eine Blocklist. Man sollte nur http:, https: und bei Bedarf mailto:, ftp:, sftp: erlauben, und relative URLs, die mit / beginnen, könnte man möglicherweise ebenfalls zulassen
    Allerdings muss man dafür wirklich alle Attribute korrekt behandeln, die tatsächlich eine URL sein können, daher ist es am Ende wahrscheinlich besser, nur einige wenige Tags samt ihrer Attribute zu erlauben

    • Wenn man keine sehr alten Browser unterstützen muss [1], ist es am einfachsten, das URL-Parsing dem Browser zu überlassen. Man kann es zum Beispiel so machen: ['http:', 'https:', 'mailto:', 'tel:'].includes(new URL(value, location.origin).protocol)
      [1] https://caniuse.com/url
    • Gemeint ist hier wohl der Abschnitt „Sanitize HTML strings“ in diesem Artikel: https://phuoc.ng/collection/html-dom/sanitize-html-strings/
      Dieser Artikel sollte nicht den Eindruck vermitteln, dass HTML-Sanitization so einfach sei. Gegen Ende wird zwar https://github.com/cure53/DOMPurify erwähnt, aber ich finde, man sollte viel deutlicher sagen, dass man so etwas nicht selbst schreiben sollte, und stattdessen ausschließlich DOMPurify empfehlen
      Ich habe dazu ein Issue eröffnet: https://github.com/phuocng/html-dom/issues/281
  • Sieht nach einer nützlichen Liste aus; ich habe noch nicht alles angesehen, aber bislang wirkt es gut
    Beim Anklicken des ersten Beispiels fiel mir auf, dass window.matchMedia('(prefers-color-scheme: dark)') unnötigerweise zweimal ausgeführt wird
    Wenn setFavicon als Event-Listener-Callback verwendet werden soll, kann man einfach event.matches aus dem an den Callback übergebenen Parameter event nutzen
    Persönlich finde ich die HTML-Seite besser, weil damit auch Nutzer unterstützt werden, bei denen JS deaktiviert ist
    https://phuoc.ng/collection/html-dom/change-the-favicon-dyna...

    • Wenn man es in HTML behandelt, verhindert das auch das kurze Aufblitzen von Inhalten eines anderen Themes. Dasselbe lässt sich auf das theme-color-Meta anwenden; für PWA-Entwickler, die auf Details achten, ist das eine wenig genutzte, aber hervorragende Funktion
  • Die Technik des „automatischen Erweiterns von textarea“ wird durch die neue CSS-Eigenschaft form-sizing allmählich überholt.
    https://chriscoyier.net/2023/09/29/css-solves-auto-expanding...
    Auch ohne diese neue CSS-Eigenschaft ist der Ansatz, die height eines Elements anzupassen, nicht ideal und kann ruckeln.
    Ein besserer Ansatz ist die Verwendung eines versteckten Spiegel-Elements.
    https://css-tricks.com/the-cleanest-trick-for-autogrowing-te...

  • Einige der hier gezeigten Dinge verwenden veraltete und unbeholfene APIs, obwohl es bessere native APIs gibt.
    Zum Beispiel ist „Element ersetzen“ als ele.parentNode.replaceChild(newEle, ele); dargestellt, aber wenn man nicht auf Chrome vor 54, Firefox vor 49 oder Safari vor 10 abzielt, kann man einfach ele.replaceWith(newEle) verwenden.
    replaceWith kann auch einen einzelnen Knoten durch mehrere Knoten oder Text ersetzen.
    Ebenso wird bei „NodeList durchlaufen“ empfohlen, erst in ein Array zu expandieren und dann forEach zu verwenden, aber for (let ele of nodelist) ... reicht völlig aus.

    • Man sollte allerdings daran denken, dass NodeList ein live Objekt sein kann. Wenn man die Liste während der Iteration verändert, kann das zu unerwarteten Ergebnissen führen.
  • Gut. Gespeichert. Als ähnlich gute Ressource gibt es auch https://youmightnotneedjquery.com/
    Ich arbeite nicht oft im Webbereich, aber jedes Mal, wenn ich es tue, verliere ich angesichts des Framework-Overkills völlig die Motivation. Dass ein neues React-Projekt mit Hunderten Abhängigkeiten startet, ist außer Kontrolle geraten, und das Gewicht dieser Komplexität ist erstaunlich.
    Dagegen sind die mitgelieferten plattformübergreifenden Browser-Technologien stärker als je zuvor, und der Codeumfang für gängige Aufgaben ist gar nicht so groß.
    Frontend-Entwickler, geht es euch gut?

    • Ich mag React oder npm überhaupt nicht besonders, aber ich denke trotzdem, dass einige Frameworks ihre Berechtigung haben, weil sie nützliche Dinge bieten, die die reine DOM-API nicht bereitstellt.
      Zum Beispiel sind Anwendungszustandsverwaltung und Routing große Themen, die man mit reinen DOM-APIs selbst implementieren müsste.
      Je nach Komplexität der App ist das vielleicht keine große Sache, aber sobald man über eine einfache App hinausgeht, steigt der Wert solcher Zusatzfunktionen schnell. Wenn man dafür allerdings Dinge braucht, die npm voraussetzen, wird es schnell lästig.
    • Eine weitere hervorragende Ressource in derselben Richtung ist das großartige https://javascript.info/
      Als Frontend-Entwickler, der die Basisplattform und ihre Fähigkeiten mag, freue ich mich über gute Entwicklungen wie verschachteltes CSS, Container Queries und die insgesamt verbesserte JS-Erfahrung seit ES6.
      Gleichzeitig erstaunt es mich, wie viele Menschen selbst für Kleinigkeiten wie Buttons oder fettgedruckten Text Komponenten verwenden.
      Ich mag Frameworks an sich, aber viel Framework- und Bibliotheksmarketing stützt sich auf den Glauben, dass CSS und reine DOM-Manipulation wahnsinnig schwer seien und dass es nicht nur schneller und einfacher, sondern auch professioneller sei, sich einfach irgendein Paket von NPM zu holen.
    • Ich stimme zu, dass es außer Kontrolle geraten ist. Allerdings bin ich im letzten Jahr in ein Plattform-Team gewechselt und habe zum ersten Mal angefangen, mit DevOps-Tools zu arbeiten, und deren Komplexität steht dem Frontend in nichts nach.
      Allein Dinge wie Kubernetes, Helm, Terraform, CircleCI bringen eine absurde Menge an übereinandergeschichteter Terminologie mit sich.
    • Ich frage mich, ob du schon einmal etwas Nichttriviales mit „leistungsfähigen plattformübergreifenden Technologien“ gemacht hast. Und React ist nicht die einzige Option.
  • Ich war wirklich überrascht, als ich erfahren habe, dass mehrere DOM-Funktionen eine automatisch aktualisierte live HTMLCollection zurückgeben.
    Ich frage mich, wie aktiv diese Funktion vor dem Framework-Hype oder rund um die Zeit, als Entwicklung ohne Frameworks wieder etwas an Popularität gewann, tatsächlich in Produktionscode genutzt wurde.

  • Alt wird wieder neu. Meine erste Frontend-Rolle bestand 1999 darin, Webanwendungen zu bauen.
    Coole Funktionen wie Drag-and-drop für Treeviews, Click-to-edit und praktisch Single-Page-Apps habe ich komplett mit „Vanilla“ JS gebaut.
    Der schwierigste Teil war, die Unterschiede zwischen Netscape und Internet Explorer auszugleichen.

    • Mich würde interessieren, wie ihr den Zustand und seine Änderungen verwaltet habt.
      Warum wirkt es so, als wüssten wir heute nicht mehr, wie man so etwas macht ;]
  • Meine derzeit liebste reine JavaScript-Funktion ist Element.insertAdjacentHTML, die es schon seit Chrome 1.0 und den IE-Zeiten gibt.
    Besonders zusammen mit mehrzeiligen Strings mit Backticks ist sie kaum genug zu loben. Ich kann kaum glauben, dass es das schon so lange gibt und ich erst vor etwa einem Jahr davon erfahren habe.
    insertAdjacentHTML(position, text) parst den angegebenen Text als HTML oder XML und fügt die resultierenden Knoten an der angegebenen Position im DOM-Baum ein.
    Mit dem ursprünglichen DOM hätte man ein li-Element erstellen, ein a-Element erstellen, es als Kind anhängen, das Attribut href setzen, den Textwert einfügen und es dann in das ul einfügen müssen. Oder man hätte alles zu einem großen String zusammenfassen und per innerHTML einsetzen müssen, und das Ändern einer bestehenden Liste war noch schmerzhafter und wortreicher.

    1. https://developer.mozilla.org/en-US/docs/Web/API/Element/ins...