为什么jQuery或诸如getElementById之类的DOM方法找不到元素?
document.getElementById
, $(“#id”)
或任何其他dom方法/jQuery选择器找不到元素的可能原因是什么?
示例问题包括:
- jQuery默默地未能绑定事件处理程序
- jQuery“ getter”方法(
.val()
,.html()
,,.text().text()< /code>)返回
未定义
- 标准DOM方法返回
null
导致几个错误中的任何一个:
unturew typeError:无法设置null的属性'...' uck typeerror:无法设置null(设置'...')
的属性 untured typeerror:无法阅读null
的属性'...' uck offult typeError:无法读取null的属性(读取'...')
最常见的形式是:
undureck typeError:无法设置null的属性'onClick'
的属性“样式”
uck offult typeerror:无法阅读null的属性'addeventListener'
uck ofture typeerror:无法阅读null
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您要找到的元素不在 noreflow noreferrer“> dom 当您的脚本运行时。
您的圆顶脚本的位置可以对其行为产生深远的影响。浏览器从上到下分析HTML文档。元素被添加到DOM中,并且(默认情况下)在遇到时被执行。 这意味着顺序很重要。通常,脚本找不到后来在标记中出现的元素,因为这些元素尚未添加到DOM中。
考虑以下标记;脚本#1无法找到
&lt; div&gt;
,而脚本2成功:那么,你该怎么办?您有几个选择:
选项1:给定上以上示例中看到的内容,移动脚本
,直观的解决方案可能就是简单地将脚本移到标记上,超越您要访问的元素。实际上,很长一段时间以来,将脚本放在页面底部被视为a best练习出于多种原因。以这种方式组织的文档的其余部分将在执行您的脚本之前进行解析:
虽然这是有道理的,并且是传统浏览器的可靠选择,但它是有限的,并且有更灵活的现代方法可用。
选项2:
defer
属性在我们确实说脚本是“(默认情况下)在遇到时执行的脚本,” 现代浏览器允许您指定不同的行为。如果您要链接外部脚本,则可以使用
defer
属性。这意味着您可以在任何地方使用
defer
标记的脚本,甚至&lt; head&gt;
,它应该可以访问完全实现的DOM。请记住...
defer
只能用于外部脚本,即:那些具有src
属性的脚本。选项3:
根据您的要求,模块可以使用 JavaScript模块。与标准脚本的其他重要区别(),模块会自动递延,不限于外部来源。
将脚本的
类型
设置为模块
,例如:选项4:延迟事件处理
添加一个侦听器,以解析文档后发射的事件。
domcontentloaded事件
窗口:加载事件
/a>事件在
domcontentloaded
和其他资源(例如样式表和图像)之后发射。因此,它的发射时间比我们目的的要求晚。不过,如果您正在考虑像IE8这样的较旧浏览器,那么支持几乎是通用的。当然,您可能想要a polyfill foraDdeventListlistener()
jQuery的
ready()
domcontentloaded
和窗口:加载
每个都有他们的警告。 jQuery'sready()
在可能的情况下,失败窗口:LOAD
在必要时,如果DOM已经完成,请立即发射其回调。您可以将Ready处理程序直接传递给jQuery,以
$( handler )
,例如:选项5:事件委托
将事件处理委托给目标元素的祖先。
当元素提出事件时(前提是它是起泡事件,没有什么可以阻止其传播),该元素的祖先中的每个父级,一直到
window
,也接收了事件。这使我们可以将处理程序从后代起泡时将处理程序附加到现有元素和样本事件上……即使是在附加处理程序后添加的后代也是从添加的后代中。我们要做的就是检查事件,以查看该事件是否是由所需元素提出的,如果是的,则运行我们的代码。通常,此模式保留给在加载时不存在或避免附加大量重复处理程序的元素。为了提高效率,请选择目标元素的最近可靠的祖先,而不是将其附加到
文档
上。如果合适,请不要忘记事件:
以防止进一步的冒泡/处理。本机JavaScript
jQuery的
on()
jQuery使此功能通过 。给定事件名称,所需后代的选择器和事件处理程序,它将解决您的委派事件处理并管理您的此上下文:
The element you were trying to find wasn’t in the DOM when your script ran.
The position of your DOM-reliant script can have a profound effect on its behavior. Browsers parse HTML documents from top to bottom. Elements are added to the DOM and scripts are (by default) executed as they're encountered. This means that order matters. Typically, scripts can't find elements that appear later in the markup because those elements have yet to be added to the DOM.
Consider the following markup; script #1 fails to find the
<div>
while script #2 succeeds:So, what should you do? You've got a few options:
Option 1: Move your script
Given what we've seen in the example above, an intuitive solution might be to simply move your script down the markup, past the elements you'd like to access. In fact, for a long time, placing scripts at the bottom of the page was considered a best practice for a variety of reasons. Organized in this fashion, the rest of the document would be parsed before executing your script:
While this makes sense, and is a solid option for legacy browsers, it's limited and there are more flexible, modern approaches available.
Option 2: The
defer
attributeWhile we did say that scripts are, "(by default) executed as they're encountered," modern browsers allow you to specify a different behavior. If you're linking an external script, you can make use of the
defer
attribute.This means that you can place a script tagged with
defer
anywhere, even the<head>
, and it should have access to the fully realized DOM.Just keep in mind...
defer
can only be used for external scripts, i.e.: those having asrc
attribute.Option 3: Modules
Depending upon your requirements, you may be able to utilize JavaScript modules. Among other important distinctions from standard scripts (noted here), modules are deferred automatically and are not limited to external sources.
Set your script's
type
tomodule
, e.g.:Option 4: Defer with event handling
Add a listener to an event that fires after your document has been parsed.
DOMContentLoaded event
DOMContentLoaded
fires after the DOM has been completely constructed from the initial parse, without waiting for things like stylesheets or images to load.Window: load event
The
load
event fires afterDOMContentLoaded
and additional resources like stylesheets and images have been loaded. For that reason, it fires later than desired for our purposes. Still, if you're considering older browsers like IE8, the support is nearly universal. Granted, you may want a polyfill foraddEventListener()
.jQuery's
ready()
DOMContentLoaded
andwindow:load
each have their caveats. jQuery'sready()
delivers a hybrid solution, usingDOMContentLoaded
when possible, failing over towindow:load
when necessary, and firing its callback immediately if the DOM is already complete.You can pass your ready handler directly to jQuery as
$(handler)
, e.g.:Option 5: Event Delegation
Delegate the event handling to an ancestor of the target element.
When an element raises an event (provided that it's a bubbling event and nothing stops its propagation), each parent in that element's ancestry, all the way up to
window
, receives the event as well. That allows us to attach a handler to an existing element and sample events as they bubble up from its descendants... even from descendants added after the handler was attached. All we have to do is check the event to see whether it was raised by the desired element and, if so, run our code.Typically, this pattern is reserved for elements that don't exist at load time or to avoid attaching a large number of duplicate handlers. For efficiency, select the nearest reliable ancestor of the target element rather than attaching it to the
document
. If appropriate, don't forgetEvent:stopPropagation()
to prevent further bubbling/processing.Native JavaScript
jQuery's
on()
jQuery makes this functionality available through
on()
. Given an event name, a selector for the desired descendant, and an event handler, it will resolve your delegated event handling and manage yourthis
context:简短而简单:,因为您要寻找的元素在文档中尚不存在(尚未)。
在此答案的其余部分中,我将使用
getElementById
示例,但同样适用于 getElementsBytagName
, 以及选择元素的任何其他DOM方法。可能的原因
有三个原因可能不存在元素:
带有传递的元素文档中确实不存在ID。您应该仔细检查您传递给
getElementById
的ID是否确实与(生成的)HTML中的现有元素的ID匹配,并且您尚未 nibsellypelled ID(ID是ID(ID是) 案例敏感!)。如果您正在使用
getElementById
,请确保您唯一给出元素的ID(例如,document.getElemnTbyId(“ the-id the-id the-id) ”)
)。如果您使用的是接受CSS选择器的方法(例如QuerySelector
),请确保您在ID之前包括#
id(例如,document.queryselector(“#the-id”)
)。您必须不使用#
与getElementById
,并且必须必须与queryselector
一起使用它。和类似。另请注意,如果ID中的字符中的字符在 css标识符(例如。
;id
包含的属性。
字符是差的,但有效),您必须使用QUERYSELECTOR
(document.queryselector(“#\\。id”)
)时逃脱那些),但使用getElementById
() > document.getElementById(“ the.id”)
)。目前不存在该元素您调用
getElementById
。即使您可以在页面上看到它,即使您可以在文档中看到它,因此该元素不在查询中,因为它在
iframe
中(这是其自己的文档)。IFRAMES中的元素
在搜索包含它们的文档时未搜索。如果问题是原因3( iframe 或类似),则需要查看
iframe
而不是父级文档中的文档,也许是通过获取< code> iframe element,并使用其 属性访问其文档(仅相同原始)。该答案的其余部分解决了前两个原因。第二个原因&nbsp; - 尚不存在 &nbsp; - 很普遍。浏览器分析并处理HTML从上到下。这意味着任何呼叫对DOM元素出现在HTML中之前发生的DOM元素的呼叫都会失败。
考虑以下示例:
div
出现script
。目前执行脚本,元素尚不存在 和getElementById
将返回null
。jQuery
使用jQuery的所有选择器也是如此。如果您拼写错误您的选择器,或者您正在尝试选择它们,则不会找到元素。
一个额外的转折是找不到jQuery,因为您已经没有协议加载了脚本并从文件系统运行:
该语法用于允许脚本通过协议https://在页面上通过https加载https https://并加载http带有协议的页面上的版本http://
不加载
file> file> file://somecdn.somewhere.com的不幸副作用
和
它具有尝试 您致电
getElementById
(或任何DOM方法),请确保要访问的元素存在,即加载DOM。可以通过简单地将您的JavaScript 放在之后来确保这一点,
在这种情况下,您还可以将代码放在关闭的主体标签之前(
&lt;/body&gt;
) (所有DOM元素将在执行脚本时可用)。其他解决方案包括收听“ noreferrer”>
load> load
[mdn] 或domcontentloaded
[mdn] 事件。在这些情况下,在文档中放置JavaScript代码并不重要,您只需要记住将所有DOM处理代码放在事件处理程序中即可。示例:
请参阅 are quirksmode.org 有关事件处理和浏览器差异的更多信息。
jQuery
首先确保正确加载jQuery。 使用浏览器的开发人员工具找出是否找到并纠正jQuery文件并纠正URL如果不是(例如,添加
http:
或https:
方案在开始时,调整路径等),请聆听
load
load /domContentLoaded
事件正是JQuery用.ready()
[docs] 。影响DOM元素的所有jQuery代码都应在该事件处理程序内部。实际上, jquery tutorial 明确指出:
另外,您也可以使用速记语法:
两者都是等效的。
Short and simple: Because the elements you are looking for do not exist in the document (yet).
For the remainder of this answer I will use
getElementById
for examples, but the same applies togetElementsByTagName
,querySelector
, and any other DOM method that selects elements.Possible Reasons
There are three reasons why an element might not exist:
An element with the passed ID really does not exist in the document. You should double check that the ID you pass to
getElementById
really matches an ID of an existing element in the (generated) HTML and that you have not misspelled the ID (IDs are case-sensitive!).If you're using
getElementById
, be sure you're only giving the ID of the element (e.g.,document.getElemntById("the-id")
). If you're using a method that accepts a CSS selector (likequerySelector
), be sure you're including the#
before the ID to indicate you're looking for an ID (e.g.,document.querySelector("#the-id")
). You must not use the#
withgetElementById
, and must use it withquerySelector
and similar. Also note that if the ID has characters in it that aren't valid in CSS identifiers (such as a.
;id
attributes containing.
characters are poor practice, but valid), you have to escape those when usingquerySelector
(document.querySelector("#the\\.id")
)) but not when usinggetElementById
(document.getElementById("the.id")
).The element does not exist at the moment you call
getElementById
.The element isn't in the document you're querying even though you can see it on the page, because it's in an
iframe
(which is its own document). Elements iniframes
aren't searched when you search the document that contains them.If the problem is reason 3 (it's in an
iframe
or similar), you need to look through the document in theiframe
, not the parent document, perhaps by getting theiframe
element and using itscontentDocument
property to access its document (same-origin only). The rest of this answer addresses the first two reasons.The second reason — it's not there yet — is quite common. Browsers parse and process the HTML from top to bottom. That means that any call to a DOM element which occurs before that DOM element appears in the HTML, will fail.
Consider the following example:
The
div
appears after thescript
. At the moment the script is executed, the element does not exist yet andgetElementById
will returnnull
.jQuery
The same applies to all selectors with jQuery. jQuery won't find elements if you misspelled your selector or you are trying to select them before they actually exist.
An added twist is when jQuery is not found because you have loaded the script without protocol and are running from file system:
this syntax is used to allow the script to load via HTTPS on a page with protocol https:// and to load the HTTP version on a page with protocol http://
It has the unfortunate side effect of attempting and failing to load
file://somecdn.somewhere.com...
Solutions
Before you make a call to
getElementById
(or any DOM method for that matter), make sure the elements you want to access exist, i.e. the DOM is loaded.This can be ensured by simply putting your JavaScript after the corresponding DOM element
in which case you can also put the code just before the closing body tag (
</body>
) (all DOM elements will be available at the time the script is executed).Other solutions include listening to the
load
[MDN] orDOMContentLoaded
[MDN] events. In these cases it does not matter where in the document you place the JavaScript code, you just have to remember to put all DOM processing code in the event handlers.Example:
Please see the articles at quirksmode.org for more information regarding event handling and browser differences.
jQuery
First make sure that jQuery is loaded properly. Use the browser's developer tools to find out whether the jQuery file was found and correct the URL if it wasn't (e.g. add the
http:
orhttps:
scheme at the beginning, adjust the path, etc.)Listening to the
load
/DOMContentLoaded
events is exactly what jQuery is doing with.ready()
[docs]. All your jQuery code that affects DOM element should be inside that event handler.In fact, the jQuery tutorial explicitly states:
Alternatively you can also use the shorthand syntax:
Both are equivalent.
基于ID的选择器不起作用的原因
solutions
在声明后尝试访问该元素,或者使用
$(docund)$(document).ready();
之类的东西
诸如来自ajax响应的元素的内容,请使用jQuery的
.bind()
方法。 jQuery的较旧版本的.live()
使用工具[例如,用于浏览器的Web -Developer插件]来查找重复的ID并删除它们。
Reasons why id based selectors don't work
Solutions
Try to access the element after its declaration or alternatively use stuff like
$(document).ready();
For elements coming from Ajax responses, use the
.bind()
method of jQuery. Older versions of jQuery had.live()
for the same.Use tools [for example, webdeveloper plugin for browsers] to find duplicate ids and remove them.
如果您要访问的元素在
iframe
中,则尝试在iframe
的上下文之外访问它,这也会导致其失败。如果您想在iFrame中获取元素,则可以找出在这里。
If the element you are trying to access is inside an
iframe
and you try to access it outside the context of theiframe
this will also cause it to fail.If you want to get an element in an iframe you can find out how here.
正如@felixkling指出的那样,最有可能的情况是您要寻找的节点尚不存在(尚不存在)。
但是,现代开发实践通常可以用文档范围来操纵文档树之外的文档元素,或者直接直接脱离/重新触及当前元素。此类技术可以用作JavaScript模板的一部分,也可以避免过度重新粉刷/反流操作,而所涉及的元素正在大大改变。
同样,在现代浏览器上推出的新“ Shadow dom”功能可以使元素成为文档的一部分,但不可用document.getElementById及其所有兄弟姐妹方法(QuerySelectector等)。这样做是为了封装功能并专门隐藏它。
再说一次,您最可能简单地寻找的元素在文档中还不是(尚未),您应该按照Felix的建议进行。但是,您还应该意识到,这越来越多的原因是元素可能是无法理解的唯一原因(无论是临时还是永久)。
As @FelixKling pointed out, the most likely scenario is that the nodes you are looking for do not exist (yet).
However, modern development practices can often manipulate document elements outside of the document tree either with DocumentFragments or simply detaching/reattaching current elements directly. Such techniques may be used as part of JavaScript templating or to avoid excessive repaint/reflow operations while the elements in question are being heavily altered.
Similarly, the new "Shadow DOM" functionality being rolled out across modern browsers allows elements to be part of the document, but not query-able by document.getElementById and all of its sibling methods (querySelector, etc.). This is done to encapsulate functionality and specifically hide it.
Again, though, it is most likely that the element you are looking for simply is not (yet) in the document, and you should do as Felix suggests. However, you should also be aware that that is increasingly not the only reason that an element might be unfindable (either temporarily or permanently).
如果脚本执行顺序不是问题,则问题的另一个可能原因是该元素未正确选择:
getElementById
要求传递的字符串为ID verbatim ,别无其他。如果将传递的字符串前缀为#
,并且ID不会以##
开头,则不会选择:类似地,对于
getelementsbyclassname < /code>,请勿将传递的字符串前缀
。
:与querySelector,queryselectorall和jQuery一起,以匹配具有特定类名称的元素,直接将
。
放在课堂上。同样,要将元素与特定ID匹配,请直接将#
放在ID之前:在大多数情况下,此处的规则与CSS选择器相同,可以详细看到在这里。
要匹配具有两个或多个属性的元素(例如两个类名称,一个类名称和一个
data-
属性),请在选择器中将每个属性的选择器彼此相邻放置string,没有将它们分开的空间(因为空间表示后代选择器)。例如,选择:使用查询字符串
.foo.bar
。选择使用查询字符串
.foo [data-bar =“ somedata”]
。要选择&lt; span&gt;
下面:使用
div.parent&gt;跨度[data-username =“ bob”]
。大写和拼写对以上所有内容都很重要。如果大写不同或拼写不同,则不会选择元素:
您还需要确保方法具有适当的资本化和拼写。使用:
之一
任何其他拼写或资本化都无法正常工作。例如,
document.getElementByClassName
会丢弃错误。确保将字符串传递给这些选择器方法。如果将不是字符串的东西传递给
QuerySelector
,getElementById
等,它几乎可以肯定不会工作。如果您要选择的元素上的html属性被引号包围,则必须是平淡的引号(单个或double);
'
或之类的卷曲引号,如果您尝试按ID,类或属性进行选择,
将无效。If script execution order is not the issue, another possible cause of the problem is that the element is not being selected properly:
getElementById
requires the passed string to be the ID verbatim, and nothing else. If you prefix the passed string with a#
, and the ID does not start with a#
, nothing will be selected:Similarly, for
getElementsByClassName
, don't prefix the passed string with a.
:With querySelector, querySelectorAll, and jQuery, to match an element with a particular class name, put a
.
directly before the class. Similarly, to match an element with a particular ID, put a#
directly before the ID:The rules here are, in most cases, identical to those for CSS selectors, and can be seen in detail here.
To match an element which has two or more attributes (like two class names, or a class name and a
data-
attribute), put the selectors for each attribute next to each other in the selector string, without a space separating them (because a space indicates the descendant selector). For example, to select:use the query string
.foo.bar
. To selectuse the query string
.foo[data-bar="someData"]
. To select the<span>
below:use
div.parent > span[data-username="bob"]
.Capitalization and spelling does matter for all of the above. If the capitalization is different, or the spelling is different, the element will not be selected:
You also need to make sure the methods have the proper capitalization and spelling. Use one of:
Any other spelling or capitalization will not work. For example,
document.getElementByClassName
will throw an error.Make sure you pass a string to these selector methods. If you pass something that isn't a string to
querySelector
,getElementById
, etc, it almost certainly won't work.If the HTML attributes on elements you want to select are surrounded by quotes, they must be plain straight quotes (either single or double); curly quotes like
‘
or”
will not work if you're trying to select by ID, class, or attribute.我正在使用Apache挂毯,就我而言,上述答案都没有帮助。最后,我发现该错误是由于使用“ ID”和“ T:ID”的相同值引起的。
我希望它有帮助。
I was using Apache Tapestry, and in my case none of the above answers helped. Finally, I found out that the error was caused by using the same value for the 'id' and 't:id'.
I hope it helps.