SELF-Wiki: Was ist das DOM?
Matthias Scharwies
- dom
- javascript
- selfhtml-wiki
Guten Morgen,
hier hatte ich es schon angekündigt: JavaScript und das DOM/Was ist das DOM?
Wir hatten an verschiedenen Stellen nahezu gleichlautende Erklärungen, die ich jetzt zu einem Anfänger-Tutorial zusammengefasst habe:
Die im Wiki vielfach vorkommende Liste der „DOM-Methoden“ würde ich ebenfalls gerne auf den Prüfstand stellen:
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Herzliche Grüße
Matthias Scharwies
@@Matthias Scharwies
- getElementById(): kann auf Elemente zugreifen, die ein dokumentweit eindeutiges id-Attribut enthalten
- getElementsByName(): kann auf Elemente zugreifen, die einen Namen besitzen (er muss nicht unbedingt eindeutig sein)
- getElementsByTagName(): kann auf alle Elemente zugreifen in der Form: "liefere mir das 27. td-Element im Dokument".
?? getElementsByTagName()
liefert alle Elemente dieses Namens. Für das 27. td-Element ist Weiteres erforderlich, was wohl nichts in dieser Übersicht verloren hat.
- querySelector(): gibt das erste Element zurück, das dem angegebenen CSS-Selektor entspricht.
- querySelectorAll(): gibt eine Liste von Elementen zurück, die dem angegebenen CSS-Selektor (auch mehrere, durch Komma getrennte, Angaben möglich) entsprechen
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Ja, mit querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dass getElementById('a')
dasselbe tut wie querySelector('#a')
.
Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetzt querySelector()
/querySelectorAll()
hat.
Kwakoni Yiquan
Moin Gunnar,
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
wie ist denn eigentlich die Performance im Vergleich zwischen den spezifischen Methoden und „query selector“?
Meine Erwartung ist, dass das Parsen des „query strings“ etwas mehr Zeit und Rechenleistung benötigt als schon direkt im DOM den entsprechend Lookup durchzuführen.
Viele Grüße
Robert
Servus!
@@Matthias Scharwies
- getElementById(): kann auf Elemente zugreifen, die ein dokumentweit eindeutiges id-Attribut enthalten
- getElementsByName(): kann auf Elemente zugreifen, die einen Namen besitzen (er muss nicht unbedingt eindeutig sein)
- getElementsByTagName(): kann auf alle Elemente zugreifen in der Form: "liefere mir das 27. td-Element im Dokument".
??
getElementsByTagName()
liefert alle Elemente dieses Namens. Für das 27. td-Element ist Weiteres erforderlich, was wohl nichts in dieser Übersicht verloren hat.
- querySelector(): gibt das erste Element zurück, das dem angegebenen CSS-Selektor entspricht.
- querySelectorAll(): gibt eine Liste von Elementen zurück, die dem angegebenen CSS-Selektor (auch mehrere, durch Komma getrennte, Angaben möglich) entsprechen
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Ja, mit
querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
Ja, danke! Seh' ich auch so!
Herzliche Grüße
Matthias Scharwies
Hallo zusammen,
Ja, mit
querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
Kann man für Neueinsteigende so machen, wobei die Erwähnung von getElementById()
, getElementsByName()
, getElementsByClassName()
, getElementsByTagName()
und (in speziellen Kontexten) getElementsByTagNameNS()
durchaus nützlich sein kann, wenn man es etwa mit älterem Code zutun hat und Anpassungen durchführen möchte.
Erwähnenswert ist aber, dass querySelector()
/ querySelectorAll()
wie andere Elements-Methoden nicht nur auf dem Document- sondern auch auf dem Element-Interface wirken können:
<ul id="spezielle_liste">
<li>Text</li>
<li>Text</li>
<li>Text</li>
</ul>
<script>
const ul = document.querySelector("#spezielle_liste");
const ul_li = ul.querySelectorAll("li");
console.log(ul_li.length); // 3
</script>
Interessanterweise klappt das mittlerweile sogar bei AJAXifizierten Inhalten, also eingelesenen XML-Strukturen. Dort war bisher xmlroot.getElementsByTagName("xmlelement") zielführend(er).
Grüße,
Thomas
Hallo Gunnar,
wobei gesagt werden muss, dass getElementById('a') dasselbe tut wie querySelector('#a').
Auf Ebene von Document oder DocumentFragment: Ja.
Auf Ebene von Element: Nein.
Denn getElementById
ist eine Methode von NonElementParentNode
, ein Mixin, das von Document
und DocumentFragment eingebunden wird. Hingegen ist querySelector
eine Methode von ParentNode
, ein Mixin, das von Document
, DocumentFragment
und Element
inkludiert wird.
Als Ergebnis sucht getElementById immer global im Dokument oder Fragment, während querySelector auf einen Element aufgerufen werden kann und dann auf dessen Scope beschränkt ist.
Ob das merkliche Performance-Auswirkungen hat, glaube ich nicht. Die CSS Selectorengine dürfte jegliche Optimierung erhalten haben, die man sich nur vorstellen kann. In riesigen DOMs könnte das Suchen in einem kleineren Teilbaum vielleicht effizienter sein. Es könnte aber auch sein, dass getElementById durch eine Hashmap optimiert wird. Müsste man testen und messen.
Funktionale Auswirkungen können sich ergeben,
a
ist kein Kind des Scope-Elements, sondern anderswo im DOM (Parent, Sibling, x-th Cousin y-th removed - frag einen Hobbit…)querySelectorAll("#a")
oder querySelector(".t #a")
fabriziere.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen.
Muss man vielleicht auch im Nebensatz erwähnen, dass querySelectorAll eine statische Nodelist liefert, aber getElementsByTagName, getElementsByClassName und children eine live HTMLCollection, getElementsByName und childNodes jedoch eine live NodeList? Warum getElementsByName eine NodeList liefert, die beiden anderen getElements-Methoden hingegen eine HTMLCollection, ist vermutlich ein Artefakt der Browserkriege, aber es ist schon eine Inkonsistenz zum Verzeifeln.
Hantieren mit live collections ist kritisch wenn man das DOM verändert. Ich würde auch wetten, dass ihre Verwendung Tempo kostet, weil sie bei jeder Verwendung neu erstellt werden müssen oder sie das DOM ständig auf Änderungen belauschen müssen. Hinzu kommt, dass man der NodeList-Schnittstelle die forEach-Methode spendiert hat und die Iterator-Quellen entries, keys und values, das würde ich als deutlichen Vorteil von querySelectorAll darstellen.
Oh. Ups. HTMLCollection implementiert den Iterator neuerdings auch?! Is ja heiß…
Gibt es Fälle, wo man unbedingt eine live-Collection aus Elementen braucht (von children
und childNodes
abgesehen)?
Interessant ist auch dieser Stackoverflow-Beitrag von 2022, der etwas zur Historie der arrayoiden Listentypen im DOM verrät.
Rolf
Guten Morgen,
Wie schon angekündigt, möchte ich am 29.01. um 20:15 einen Workshop auf Discord veranstalten.
Thema: JavaScript und das DOM
Hier geht es um das 1. und 3. Kapitel, bei denen ich einerseits Verbesserungsbedarf sah, jetzt aber nicht weiß, ob ich, bzw. das Tutorial in die richtige Richtung laufe(n).
hier hatte ich es schon angekündigt: JavaScript und das DOM/Was ist das DOM?
Wir hatten an verschiedenen Stellen nahezu gleichlautende Erklärungen, die ich jetzt zu einem Anfänger-Tutorial zusammengefasst habe:
- kurze Einleitung
- Überschrift #DOM als Baumstruktur
Jetzt wird der Elementbaum gezeigt, der Begriff node eingeführt und mit dem „Node-Inspektor“ veranschaulicht.- #Elementknoten
muss da noch ein Beispiel hin, oder reicht der „Node-Inspektor“?
Das Tutorial ist ja geplant als erste Begegnung mit dem DOM - im Nachhinein würde ich hier am node-Inspektor einen Hinweis platzieren, dass wir so etwas in den Folgekapiteln selbst bauen werden.
Und deshalb sollte irgendwann auch mal im Tutorial ein kleineres Beispiel selbst entwickelt werden. Deshalb stelle ich am 14.01. diese Frage:
Die beiden h3-Überschriften und Abschnitte könnten evtl. nach oben, evtl. aber auch nicht. Würde ich gerne diskutieren.
Mein Vorschlag: Das "Hallo Welt"-Beispiel aus #Elementknoten_ansprechen gleich in den oberen Abschnitt #Elementknoten integrieren.
Dann würde ich - wenn wir das so beschließen - die Abschnitte "Textknoten" (ein Einzeiler) und "#Textknoten ansprechen" zusammenfassen. Dort geht es um innerHTML und die bessere Eigenschaft textContent.[1]
Problem dieser Vorgehensweise: Der Abschnitt über Elementknoten enthält bereits den (noch nicht erklärten) Textknoten.
Alternative: Die drei Abschnitte direkt in die Liste der farbigen Knotentypen integrieren und dann nach dem Theoriekapitel eben das Kapitel DOM-Methoden lassen. Ich mag nämlich den Einleitungssatz:
Dieser Elementbaum ist jedoch nicht statisch, sondern kann durch DOM-Manipulation ausgelesen, verändert und erweitert werden.
Ausgehend von einem ermittelten Elementknoten lässt sich dann schnell auf dessen Attribute und Inhalt zugreifen.
Wer hat eine Idee zu einem besseren Beispiel, das evtl. auch mit Element.hasAttributes arbeitet.
Das ist hier das Problem: Attributknoten würde ich heute mit classList, querySelector() und matches() ansprechen. Habt ihr einen Use Case, in dem es wirklich vorrangig um Attribute geht?
Dann könnte man das hier so kurz lassen und auf ein anderes Beispiel weiter hinten/woanders verweisen.
Wie gesagt: Es geht um ein Anfänger-Tutorial, in dem erste Schritte der Erzeugung und Veränderung von Elenenten gezeigt werden sollten.
Da war der Bildwechsler ideal:
Aus …
<a href="peru-3.jpg">
<img src="peru-3-sm.jpg" alt="Peru 2007: Machu Picchu">
</a>
nehmen wir href, alt und fügen es in einem dialog-Element in ein neues Bild ein. Den Link unterdrücken wir mit preventDefault.
Das Script war imho auch für Anfänger verständlich:
document.querySelector('.gallery').addEventListener('click',function (evt) {
evt.preventDefault();
let element = event.target;
let parentURL = element.parentNode.href;
let imgAlt = event.target.alt;
let img = document.querySelector('#lightbox img');
img.src = parentURL;
img.alt = imgAlt;
lightbox.showModal();
});
document.getElementById('close-dialog').addEventListener('click', () => {
lightbox.close();
});
Das Erzeugen der Buttons und die Weiter-Methode mit closest schienen mir zu schwierig, weswegen ich den Neuansatz mit der ToDo-Liste anfing. Sie ist aber im halbfertigen Zustand bereits komplexer als der Bildwechsler.
@Felix Riesterer schlug folgendes vor:
Wie wäre es mit einem Anwendungsbeispiel, welches z.B. eine tabellarische Darstellung von Informationen interaktiv nutzbar macht? Etwas in der Art, wie wir auf unseren Profil-Seiten unser Postingaufkommen in einer Diagrammkurve dargestellt bekommen, vielleicht? Du hattest doch mal die Idee zu einem Vokabeltrainer...?
Das wäre der Zeitpunkt unseren Workshop für ein Brainstorming / Getränke- und Pinkelpause für 10min zu unterbrechen.
Anschließend könnte man die verschiedenen Ideen zu Anwendungsfällen diskutieren. Und im Idealfall eine attraktive, anfängergerechte und trotzdem anspruchsvolle Aufgabe finden. Die Umsetzung würde ich dann übernehmen.
Eigentlich könnte das noch ins 1. Kapitel, würde dort aber aus einem Tutorial einen theoretischen Grundlagenartikel machen. Hier (oder in einer eigenen Seite) wäre es eine gute Wiederholung zum DOM-tree und jetzt stellt sich mir die Frage:
Gibt es einen Anwendungsfall, in dem man heute noch parentNode und childNodes beötigt?
ChatGPT spuckte mir hier aus, das man beim Durchsuchen von textContent auf verbotene Inhalte durch den DOM-Tree gehen könnte.
Hat jemand eine zündende Idee?
Hier gibt es viele Beispiele, die noch von Stefan Münz stammen. document.write
und onclick
sind entfernt, trotzdem könnten viele Seiten ein Gardening vertragen:
titel=...
ins BeispielWer Lust hat, kurz eine kleinere Seite zu überarbeiten - nur zu! Freiwillige vor!
Ich würde mich freuen, wenn am Mittwoch einige aufschlagen würden und wir gemeinsam eines der wichtigsten Tutorials verbessern könnten!
Herzliche Grüße
Matthias Scharwies
Auf JavaScript/DOM/Node/textContent findet sich ein tutorialartiger Vergleich von innerHTML vs innerText vs textContent - das müsste man abgleichen. ↩︎
Guten Morgen,
vielen Dank an die Teilnehmer des Workshops am Mittwoch. Auch wenn wir nur zur viert waren, konnten wir doch einiges klären!
Thema: JavaScript und das DOM
Hier geht es um das 1. und 3. Kapitel, bei denen ich einerseits Verbesserungsbedarf sah, jetzt aber nicht weiß, ob ich, bzw. das Tutorial in die richtige Richtung laufe(n).
1. Was ist das DOM?
Das Kapitel ist jetzt aufgeräumt und in sich stimmig. Der Node-Inpektor zeigt als {{LiveBeispiel}} gleich die verschiedenen Knoten.
Dann folgt ein "Hallo Welt"-Beispiel aus dem Einstieg, bei dem das alert()
jetzt durch
document.getElementById('info').textContent = 'Hallo Welt!';
ersetzt wird. Dieses Beispiel wird dann step by step ausgebaut. Am Ende winken dann Fortsetzungsvorlage und Cards zu den Folge-Tutorials.
Schaut mal rein!
3. DOM-Manipulation
...weswegen ich den Neuansatz mit der ToDo-Liste anfing. Sie ist aber im halbfertigen Zustand bereits komplexer als der Bildwechsler.
Da haben wir einige Ideen gesammelt, die ich jetzt sukzessive umsetzen will.
4. DOM-Traversal
Eigentlich könnte das noch ins 1. Kapitel, würde dort aber aus einem Tutorial einen theoretischen Grundlagenartikel machen.
Hier wird noch einmal der Elementbaum mit seinen Verzweigungen, aber auch mit seinen „Früchtchen“ in Form von /n-Textknoten visualisiert, besonders im {{LiveBeispiel}} zu den childNodes, das wir schon hatten, hier jetzt aber wirklich reinpasst!
X. unsere Referenzseiten
Hier habe ich mich wirklich geärgert, wie kurz manche Seiten waren. So gab es Links von parentElement zurück auf parentNode, der eigentlich wichtigere Link in die Gegenrichtung fehlte. Hier habe ich eine Seite angelegt, die in die betreffenden Referenzartikel eingebunden wird. Sieht doch gleich viel besser aus!
Dieser Beziehungsinspektor ist nur eins von mehreren neuen Beispielen, die das Ganze anschaulicher machen.
Edit von Rolf: Link zum Beziehungsinspektor
Herzliche Grüße
Matthias Scharwies