- 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
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.“
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
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
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
Schon
value.startsWith('javascript:')allein erzeugt eine Schwachstelle. Vor der URL kann beliebiger Whitespace stehen, daher braucht man mindestensvalue.trim().startsWith('javascript:')Trotzdem halte ich eine Allowlist für besser als eine Blocklist. Man sollte nur
http:,https:und bei Bedarfmailto:,ftp:,sftp:erlauben, und relative URLs, die mit/beginnen, könnte man möglicherweise ebenfalls zulassenAllerdings 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
['http:', 'https:', 'mailto:', 'tel:'].includes(new URL(value, location.origin).protocol)[1] https://caniuse.com/url
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 wirdWenn
setFaviconals Event-Listener-Callback verwendet werden soll, kann man einfachevent.matchesaus dem an den Callback übergebenen ParametereventnutzenPersö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...
theme-color-Meta anwenden; für PWA-Entwickler, die auf Details achten, ist das eine wenig genutzte, aber hervorragende FunktionDie 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
heighteines 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 einfachele.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
forEachzu verwenden, aberfor (let ele of nodelist) ...reicht völlig aus.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?
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.
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.
Allein Dinge wie Kubernetes, Helm, Terraform, CircleCI bringen eine absurde Menge an übereinandergeschichteter Terminologie mit sich.
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.
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, eina-Element erstellen, es als Kind anhängen, das Attributhrefsetzen, den Textwert einfügen und es dann in dasuleinfügen müssen. Oder man hätte alles zu einem großen String zusammenfassen und perinnerHTMLeinsetzen müssen, und das Ändern einer bestehenden Liste war noch schmerzhafter und wortreicher.