Was sind die möglichen Gründe dafür document.getElementById
, dass $("#id")
eine andere DOM-Methode / ein anderer jQuery-Selektor die Elemente nicht findet?
Beispielprobleme umfassen:
- jQuery kann einen Ereignishandler stillschweigend nicht binden
- jQuery "Getter" -Methoden (
.val()
,.html()
,.text()
) zurückkehrundefined
- Eine Standard-DOM-Methode,
null
die zurückgibt und zu mehreren Fehlern führt:
Nicht erfasster TypeError: Eigenschaft '...' von null kann nicht festgelegt werden Nicht erfasster TypeError: Eigenschaft '...' von null kann nicht gelesen werden
Die häufigsten Formen sind:
Nicht erfasster TypeError: Die Eigenschaft 'onclick' von null kann nicht festgelegt werden
Nicht erfasster TypeError: Die Eigenschaft 'addEventListener' von null kann nicht gelesen werden
Nicht erfasster TypeError: Die Eigenschaft 'style' von null kann nicht gelesen werden
javascript
jquery
dom
Felix Kling
quelle
quelle
Antworten:
Das Element, das Sie suchen wollten, befand sich nicht im DOM, als Ihr Skript ausgeführt wurde.
Die Position Ihres DOM-abhängigen Skripts kann einen tiefgreifenden Einfluss auf sein Verhalten haben. Browser analysieren HTML-Dokumente von oben nach unten. Dem DOM werden Elemente hinzugefügt und Skripte werden (im Allgemeinen) ausgeführt, sobald sie angetroffen werden. Dies bedeutet, dass die Reihenfolge wichtig ist. In der Regel können Skripte keine Elemente finden, die später im Markup angezeigt werden, da diese Elemente noch nicht zum DOM hinzugefügt werden müssen.
Betrachten Sie das folgende Markup. Skript Nr. 1 findet das nicht,
<div>
während Skript Nr. 2 erfolgreich ist:Also, was solltest du tun? Sie haben einige Möglichkeiten:
Option 1: Verschieben Sie Ihr Skript
Bewegen Sie Ihr Skript weiter nach unten, kurz vor dem schließenden Body-Tag. Auf diese Weise organisiert, wird der Rest des Dokuments analysiert, bevor Ihr Skript ausgeführt wird:
Hinweis: Das Platzieren von Skripten am unteren Rand wird im Allgemeinen als bewährte Methode angesehen .
Option 2: jQuery's
ready()
Verschieben Sie Ihr Skript, bis das DOM vollständig analysiert wurde. Verwenden Sie dazu :
$(handler)
Hinweis: Sie können einfach an
DOMContentLoaded
oder binden, aber jeder hat seine Vorbehalte. jQuery's liefert eine Hybridlösung.window.onload
ready()
Option 3: Ereignisdelegation
Wenn ein Element ein Ereignis auslöst (vorausgesetzt, es ist ein sprudelndes Ereignis und nichts stoppt seine Ausbreitung), erhält auch jedes übergeordnete Element in der Abstammung dieses Elements das Ereignis. Auf diese Weise können wir einen Handler an ein vorhandenes Element anhängen und Ereignisse abtasten, wenn diese aus seinen Nachkommen sprudeln ... auch solche, die nach dem Anhängen des Handlers hinzugefügt wurden. Wir müssen lediglich das Ereignis überprüfen, um festzustellen, ob es vom gewünschten Element ausgelöst wurde, und in diesem Fall unseren Code ausführen.
jQuery's
on()
führt diese Logik für uns aus. Wir geben einfach einen Ereignisnamen, eine Auswahl für den gewünschten Nachkommen und einen Ereignishandler an:Hinweis: In der Regel ist dieses Muster für Elemente reserviert, die zum Zeitpunkt des Ladens nicht vorhanden waren, oder um das Anhängen einer großen Anzahl von Handlern zu vermeiden. Es ist auch erwähnenswert, dass Sie, obwohl ich
document
(zu Demonstrationszwecken) einen Handler angehängt habe , den nächstgelegenen zuverlässigen Vorfahren auswählen sollten.Option 4: Das
defer
AttributVerwenden Sie das
defer
Attribut von<script>
.Als Referenz ist hier der Code aus diesem externen Skript :
Hinweis: Das
defer
Attribut scheint sicherlich ein Wundermittel zu sein, aber es ist wichtig, sich der Einschränkungen bewusst zu sein ...1.
defer
Kann nur für externe Skripte verwendet werden, dh für solche mit einemsrc
Attribut.2. Beachten Sie die Browserunterstützung , dh die fehlerhafte Implementierung in IE <10
quelle
<head>
und verwende esdefer
für Skripte (ich muss keine schlechten alten inkompatiblen Browser unterstützen)defer
undasync
eine ziemlich breite Unterstützung - auch wenn sie auf einige viel ältere Browserversionen zurückgreifen. Sie haben den zusätzlichen Vorteil, das beabsichtigte Verhalten klar und explizit zu signalisieren. Denken Sie daran, dass diese Attribute nur für Skripte funktionieren, die einsrc
Attribut angeben , dh für externe Skripte. Wägen Sie die Vorteile ab. Vielleicht beides verwenden? Ihr Anruf.Kurz und einfach: Weil die Elemente, nach denen Sie suchen, (noch) nicht im Dokument vorhanden sind.
Für den Rest dieser Antwort wird ich
getElementById
als Beispiel, aber das gleiche gilt fürgetElementsByTagName
,querySelector
und andere Verfahren , dass DOM wählt Elemente.Mögliche Gründe
Es gibt zwei Gründe, warum ein Element möglicherweise nicht vorhanden ist:
Ein Element mit der übergebenen ID ist im Dokument wirklich nicht vorhanden. Sie sollten überprüfen, ob die ID, an die Sie übergeben,
getElementById
wirklich mit der ID eines vorhandenen Elements im (generierten) HTML übereinstimmt und ob Sie die ID nicht falsch geschrieben haben (bei IDs wird zwischen Groß- und Kleinschreibung unterschieden !).Im übrigen wird in der Mehrzahl der modernen Browser , die Umsetzung
querySelector()
undquerySelectorAll()
Methoden, CSS-Notation verwendet wird , ein Element von seinen abzurufenid
, zum Beispiel:document.querySelector('#elementID')
wie das Verfahren im Gegensatz von dem ein Element durch seine abgerufen wirdid
unterdocument.getElementById('elementID')
; im ersten#
Fall ist das Zeichen wesentlich, im zweiten Fall würde es dazu führen, dass das Element nicht abgerufen wird.Das Element ist zum Zeitpunkt Ihres Aufrufs nicht vorhanden
getElementById
.Der letztere Fall ist ziemlich häufig. Browser analysieren und verarbeiten den HTML-Code von oben nach unten. Das bedeutet, dass jeder Aufruf eines DOM-Elements, der vor dem Erscheinen dieses DOM-Elements im HTML erfolgt, fehlschlägt.
Betrachten Sie das folgende Beispiel:
Das
div
erscheint nach demscript
. Im Moment ist das Skript ausgeführt wird, wird das Element nicht existiert noch undgetElementById
wird zurückkehrennull
.jQuery
Gleiches gilt für alle Selektoren mit jQuery. jQuery findet keine Elemente, wenn Sie Ihren Selektor falsch geschrieben haben oder versuchen, sie auszuwählen, bevor sie tatsächlich vorhanden sind .
Eine zusätzliche Wendung ist, wenn jQuery nicht gefunden wird, weil Sie das Skript ohne Protokoll geladen haben und vom Dateisystem ausgeführt werden:
Diese Syntax wird verwendet, um das Laden des Skripts über HTTPS auf eine Seite mit dem Protokoll https: // und das Laden der HTTP-Version auf eine Seite mit dem Protokoll http: // zu ermöglichen
Es hat den unglücklichen Nebeneffekt, dass versucht wird und nicht geladen wird
file://somecdn.somewhere.com...
Lösungen
Stellen Sie vor dem Aufrufen
getElementById
(oder einer anderen DOM-Methode) sicher, dass die Elemente vorhanden sind, auf die Sie zugreifen möchten, dh das DOM wird geladen.Dies kann sichergestellt werden, indem Sie einfach Ihr JavaScript nach dem entsprechenden DOM-Element setzen
In diesem Fall können Sie den Code auch direkt vor dem schließenden Body-Tag (
</body>
) einfügen (alle DOM-Elemente sind zum Zeitpunkt der Ausführung des Skripts verfügbar).Andere Lösungen umfassen das Abhören der Ereignisse
load
[MDN] oderDOMContentLoaded
[MDN] . In diesen Fällen spielt es keine Rolle, wo in dem Dokument Sie den JavaScript-Code platzieren. Sie müssen lediglich daran denken, den gesamten DOM-Verarbeitungscode in die Ereignishandler einzufügen.Beispiel:
Weitere Informationen zur Ereignisbehandlung und zu Browserunterschieden finden Sie in den Artikeln auf quirksmode.org .
jQuery
Stellen Sie zunächst sicher, dass jQuery ordnungsgemäß geladen ist. Verwenden Sie die Entwicklertools des Browsers, um herauszufinden, ob die jQuery-Datei gefunden wurde, und korrigieren Sie die URL, wenn dies nicht der Fall ist (z. B. fügen Sie das Schema
http:
oderhttps:
am Anfang hinzu, passen Sie den Pfad an usw.).Das Abhören der
load
/DOMContentLoaded
-Ereignisse ist genau das, was jQuery mit.ready()
[docs] macht . Der gesamte jQuery-Code, der sich auf das DOM-Element auswirkt, sollte sich in diesem Ereignishandler befinden.Tatsächlich heißt es im jQuery-Tutorial explizit:
Alternativ können Sie auch die Kurzsyntax verwenden:
Beide sind gleichwertig.
quelle
ready
Ereignisses zu ändern , um die "neuere" bevorzugte Syntax widerzuspiegeln, oder ist es besser, es unverändert zu lassen, damit es in älteren Versionen funktioniert?$(window).load()
(und möglicherweise syntaktischen Alternativen zu dem$(document).ready()
,$(function(){})
es im Zusammenhang scheint, aber es? Fühlt sich leicht tangential zu dem Punkt , Sie machen..load
. Syntaxalternativen können in der Dokumentation nachgeschlagen werden. Da die Antworten jedoch in sich geschlossen sein sollten, lohnt es sich möglicherweise, sie hinzuzufügen. Andererseits bin ich mir ziemlich sicher, dass dieses spezielle Bit über jQuery bereits beantwortet wurde und wahrscheinlich in anderen Antworten behandelt wird und eine Verknüpfung damit möglicherweise ausreicht..load
ist veraltet: api.jquery.com/load-event . Ich weiß nicht, ob es nur für Bilder ist oderwindow
auch.Gründe, warum ID-basierte Selektoren nicht funktionieren
Lösungen
Versuchen Sie, nach der Deklaration auf das Element zuzugreifen, oder verwenden Sie alternativ Dinge wie
$(document).ready();
Verwenden Sie für Elemente, die aus Ajax-Antworten stammen, die
.bind()
Methode von jQuery. Ältere Versionen von jQuery hatten.live()
das gleiche.Verwenden Sie Tools [z. B. das Webentwickler-Plugin für Browser], um doppelte IDs zu finden und diese zu entfernen.
quelle
Wie @FelixKling hervorhob, besteht das wahrscheinlichste Szenario darin, dass die gesuchten Knoten (noch) nicht vorhanden sind.
Moderne Entwicklungspraktiken können jedoch häufig Dokumentelemente außerhalb des Dokumentbaums entweder mit DocumentFragments oder einfach durch direktes Trennen / erneutes Anhängen aktueller Elemente bearbeiten. Solche Techniken können als Teil der JavaScript-Vorlage oder zur Vermeidung übermäßiger Repaint- / Reflow-Vorgänge verwendet werden, während die betreffenden Elemente stark geändert werden.
In ähnlicher Weise ermöglicht die neue "Shadow DOM" -Funktionalität, die in modernen Browsern eingeführt wird, dass Elemente Teil des Dokuments sind, jedoch nicht von document.getElementById und allen seinen Geschwistermethoden (querySelector usw.) abfragbar sind. Dies geschieht, um die Funktionalität zu kapseln und gezielt auszublenden.
Wiederum ist es jedoch höchstwahrscheinlich, dass das Element, nach dem Sie suchen, (noch) nicht im Dokument enthalten ist, und Sie sollten tun, was Felix vorschlägt. Sie sollten sich jedoch auch darüber im Klaren sein, dass dies zunehmend nicht der einzige Grund ist, warum ein Element (vorübergehend oder dauerhaft) möglicherweise nicht auffindbar ist.
quelle
Wenn sich das Element, auf das Sie zugreifen möchten, innerhalb eines Elements befindet
iframe
und Sie versuchen, außerhalb des Kontexts des Elements darauf zuzugreifen, schlägtiframe
dies ebenfalls fehl.Wenn Sie ein Element in einem Iframe zu erhalten , wie Sie herausfinden können , hier .
quelle
Wenn die Skriptausführungsreihenfolge nicht das Problem ist, besteht eine weitere mögliche Ursache für das Problem darin, dass das Element nicht richtig ausgewählt wird:
getElementById
erfordert, dass die übergebene Zeichenfolge wörtlich die ID ist , und sonst nichts. Wenn Sie der übergebenen Zeichenfolge ein Präfix voranstellen#
und die ID nicht mit a beginnt#
, wird nichts ausgewählt:In ähnlicher Weise dürfen Sie
getElementsByClassName
der übergebenen Zeichenfolge nicht Folgendes voranstellen.
:Um mit querySelector, querySelectorAll und jQuery ein Element mit einem bestimmten Klassennamen abzugleichen, setzen Sie ein
.
direkt vor die Klasse. Um ein Element mit einer bestimmten ID abzugleichen, setzen Sie ein#
direkt vor die ID:Die Regeln hier sind in den meisten Fällen identisch mit denen für CSS-Selektoren und können hier im Detail eingesehen werden .
Um ein Element mit zwei oder mehr Attributen (z. B. zwei Klassennamen oder einen Klassennamen und ein
data-
Attribut) abzugleichen, setzen Sie die Selektoren für jedes Attribut nebeneinander in die Auswahlzeichenfolge, ohne dass ein Leerzeichen sie trennt (da ein Leerzeichen angibt) der Nachkommenselektor ). Zum Beispiel, um Folgendes auszuwählen:Verwenden Sie die Abfragezeichenfolge
.foo.bar
. AuswählenVerwenden Sie die Abfragezeichenfolge
.foo[data-bar="someData"]
. So wählen Sie<span>
Folgendes aus:verwenden
div.parent > span[data-username="bob"]
.Groß- und Kleinschreibung und Rechtschreibung sind für alle oben genannten Punkte von Bedeutung. Wenn die Groß- oder Kleinschreibung oder die Schreibweise unterschiedlich ist, wird das Element nicht ausgewählt:
Sie müssen auch sicherstellen, dass die Methoden die richtige Groß- und Kleinschreibung und Rechtschreibung haben. Verwenden Sie eine der folgenden Optionen:
Jede andere Schreibweise oder Großschreibung funktioniert nicht. Zum Beispiel
document.getElementByClassName
wird ein Fehler ausgelöst.Stellen Sie sicher, dass Sie diesen Auswahlmethoden eine Zeichenfolge übergeben. Wenn Sie etwas übergeben , die kein String ist
querySelector
,getElementById
usw., wird es mit ziemlicher Sicherheit nicht.quelle
Als ich Ihren Code ausprobiert habe, hat es funktioniert.
Der einzige Grund, warum Ihr Ereignis nicht funktioniert, kann sein, dass Ihr DOM nicht bereit war und Ihre Schaltfläche mit der ID "event-btn" noch nicht bereit war. Und Ihr Javascript wurde ausgeführt und versucht, das Ereignis mit diesem Element zu verbinden.
Bevor Sie das DOM-Element zum Binden verwenden, sollte dieses Element bereit sein. Dafür gibt es viele Möglichkeiten.
Option 1: Sie können Ihren Ereignisbindungscode innerhalb des dokumentbereiten Ereignisses verschieben. Mögen:
Option 2: Sie können das Timeout-Ereignis verwenden, sodass die Bindung um einige Sekunden verzögert wird. mögen:
Option 3: Verschieben Sie Ihr Javascript-Include an den unteren Rand Ihrer Seite.
Ich hoffe das hilft dir.
quelle
Das Problem ist, dass das dom-Element 'speclist' zum Zeitpunkt der Ausführung des Javascript-Codes nicht erstellt wird. Also habe ich den Javascript-Code in eine Funktion eingefügt und diese Funktion beim Body-Onload-Ereignis aufgerufen.
quelle
Meine Lösung bestand darin, die ID eines Ankerelements nicht zu verwenden :
<a id='star_wars'>Place to jump to</a>
. Anscheinend haben Blazor und andere Spa-Frameworks Probleme, auf derselben Seite zu Ankern zu springen. Um das zu umgehen, musste ich verwendendocument.getElementById('star_wars')
. Dies funktionierte jedoch nicht, bis ich stattdessen die ID in ein Absatzelement einfügte :<p id='star_wars'>Some paragraph<p>
.Beispiel mit Bootstrap:
quelle