什么是文件可能的原因。getElementById, $(“#id”)或任何其他DOM方法/ jQuery选择器找不到元素?

示例问题包括:

jQuery无声地绑定事件处理程序失败 jQuery“getter”方法(.val(), .html(), .text())返回undefined 一个标准的DOM方法返回null,导致以下任何错误:

无法设置属性'…null的' 无法设置null属性(设置'…') 无法读取属性…null的' 无法读取null属性(读取'…')

最常见的形式是:

无法将属性“onclick”设置为空 无法读取属性“addEventListener”为空 无法读取属性'style'为null


当前回答

简单地说:因为您要查找的元素(目前)还不存在于文档中。


对于这个答案的其余部分,我将使用getElementById作为示例,但同样适用于getElementsByTagName、querySelector和任何其他选择元素的DOM方法。

可能的原因

一个元素不存在的原因有三个:

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 (like querySelector), 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 # with getElementById, and must use it with querySelector 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 using querySelector (document.querySelector("#the\\.id"))) but not when using getElementById (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 in iframes aren't searched when you search the document that contains them.

如果问题是原因3(它在iframe或类似文件中),则需要查看iframe中的文档,而不是父文档,方法可能是获取iframe元素并使用其contentDocument属性访问其文档(仅同源)。这个答案的其余部分解决了前两个原因。

第二个原因——目前还没有——很常见。浏览器从上到下解析和处理HTML。这意味着在HTML中出现DOM元素之前对DOM元素的任何调用都将失败。

考虑下面的例子:

<script>
    var element = document.getElementById('my_element');
</script>

<div id="my_element"></div>

div出现在脚本之后。在脚本执行时,元素还不存在,getElementById将返回null。

jQuery

这同样适用于jQuery的所有选择器。如果你的选择器拼写错误,或者你试图在元素实际存在之前选择它们,jQuery将无法找到它们。

一个额外的扭曲是,当你没有找到jQuery,因为你已经加载了脚本没有协议,并从文件系统运行:

<script src="//somecdn.somewhere.com/jquery.min.js"></script>

此语法用于允许脚本在协议为https://的页面上通过HTTPS加载,并在协议为http://的页面上加载HTTP版本

它有一个不幸的副作用,试图加载文件失败://somecdn.somewhere.com…


解决方案

在调用getElementById(或任何与此相关的DOM方法)之前,确保要访问的元素存在,即DOM已加载。

只需将JavaScript放在相应的DOM元素之后就可以确保这一点

<div id="my_element"></div>

<script>
    var element = document.getElementById('my_element');
</script>

在这种情况下,你也可以把代码放在body结束标记(</body>)之前(所有DOM元素在脚本执行时都是可用的)。

其他解决方案包括监听load [MDN]或DOMContentLoaded [MDN]事件。在这些情况下,将JavaScript代码放在文档中的什么位置并不重要,只需记住将所有DOM处理代码放在事件处理程序中即可。

例子:

window.onload = function() {
    // process DOM elements here
};

// or

// does not work IE 8 and below
document.addEventListener('DOMContentLoaded', function() {
    // process DOM elements here
});

有关事件处理和浏览器差异的更多信息,请参阅quirksmode.org上的文章。

jQuery

首先确保正确加载了jQuery。使用浏览器的开发工具来找出jQuery文件是否被找到,如果没有,就纠正URL(例如,在开头添加http:或https:方案,调整路径等)。

监听load/DOMContentLoaded事件正是jQuery使用.ready() [docs]所做的事情。所有影响DOM元素的jQuery代码都应该在该事件处理程序中。

事实上,jQuery教程明确指出:

当使用jQuery时,我们所做的几乎所有事情都是读取或操作文档对象模型(DOM),我们需要确保一旦DOM准备好,我们就开始添加事件等。

为此,我们为文档注册一个就绪事件。 $(文档)时函数(){

   // do stuff when DOM is ready
});

或者你也可以使用简写语法:

$(function() {
    // do stuff when DOM is ready
});

两者是等价的。

其他回答

如果您试图访问的元素在iframe内部,而您试图在iframe上下文之外访问它,这也会导致它失败。

如果你想在iframe中获取一个元素,你可以在这里找到方法。

基于id的选择器不能工作的原因

指定id的元素/DOM还不存在。 元素存在,但它没有在DOM中注册[如果从Ajax响应动态追加HTML节点]。 存在多个具有相同id的元素,这将导致冲突。

解决方案

尝试在元素声明之后访问它,或者使用类似于$(document).ready()的东西; 对于来自Ajax响应的元素,使用jQuery的.bind()方法。旧版本的jQuery使用.live()来实现同样的功能。 使用工具[例如,浏览器的webdeveloper插件]找到重复的id并删除它们。

如果脚本执行顺序不是问题,另一个可能的原因是元素没有被正确选择:

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: <div id="foo"></div> // Error, selected element will be null: document.getElementById('#foo') // Fix: document.getElementById('foo') Similarly, for getElementsByClassName, don't prefix the passed string with a .: <div class="bar"></div> // Error, selected element will be undefined: document.getElementsByClassName('.bar')[0] // Fix: document.getElementsByClassName('bar')[0] 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: <div class="baz"></div> // Error, selected element will be null: document.querySelector('baz') $('baz') // Fix: document.querySelector('.baz') $('.baz') 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: <div class="foo bar"></div> use the query string .foo.bar. To select <div class="foo" data-bar="someData"></div> use the query string .foo[data-bar="someData"]. To select the <span> below: <div class="parent"> <span data-username="bob"></span> </div> 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: <div class="result"></div> // Error, selected element will be null: document.querySelector('.results') $('.Result') // Fix: document.querySelector('.result') $('.result') You also need to make sure the methods have the proper capitalization and spelling. Use one of: $(selector) document.querySelector document.querySelectorAll document.getElementsByClassName document.getElementsByTagName document.getElementById 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.

正如@FelixKling指出的那样,最有可能的情况是您正在寻找的节点(目前)还不存在。

然而,现代开发实践通常可以在文档树之外操作文档元素,可以使用DocumentFragments,也可以直接分离/重新附加当前元素。这样的技术可以作为JavaScript模板的一部分,或者在有问题的元素被大量修改时避免过度的重绘/回流操作。

类似地,在现代浏览器中推出的新的“Shadow DOM”功能允许元素成为文档的一部分,但不能按文档查询。getElementById及其所有兄弟方法(querySelector等)。这样做是为了封装功能并具体地隐藏它。

但是,您所寻找的元素很可能(还)不在文档中,您应该按照Felix的建议去做。但是,您也应该意识到,这越来越不是一个元素可能无法找到(无论是暂时的还是永久的)的唯一原因。

简单地说:因为您要查找的元素(目前)还不存在于文档中。


对于这个答案的其余部分,我将使用getElementById作为示例,但同样适用于getElementsByTagName、querySelector和任何其他选择元素的DOM方法。

可能的原因

一个元素不存在的原因有三个:

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 (like querySelector), 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 # with getElementById, and must use it with querySelector 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 using querySelector (document.querySelector("#the\\.id"))) but not when using getElementById (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 in iframes aren't searched when you search the document that contains them.

如果问题是原因3(它在iframe或类似文件中),则需要查看iframe中的文档,而不是父文档,方法可能是获取iframe元素并使用其contentDocument属性访问其文档(仅同源)。这个答案的其余部分解决了前两个原因。

第二个原因——目前还没有——很常见。浏览器从上到下解析和处理HTML。这意味着在HTML中出现DOM元素之前对DOM元素的任何调用都将失败。

考虑下面的例子:

<script>
    var element = document.getElementById('my_element');
</script>

<div id="my_element"></div>

div出现在脚本之后。在脚本执行时,元素还不存在,getElementById将返回null。

jQuery

这同样适用于jQuery的所有选择器。如果你的选择器拼写错误,或者你试图在元素实际存在之前选择它们,jQuery将无法找到它们。

一个额外的扭曲是,当你没有找到jQuery,因为你已经加载了脚本没有协议,并从文件系统运行:

<script src="//somecdn.somewhere.com/jquery.min.js"></script>

此语法用于允许脚本在协议为https://的页面上通过HTTPS加载,并在协议为http://的页面上加载HTTP版本

它有一个不幸的副作用,试图加载文件失败://somecdn.somewhere.com…


解决方案

在调用getElementById(或任何与此相关的DOM方法)之前,确保要访问的元素存在,即DOM已加载。

只需将JavaScript放在相应的DOM元素之后就可以确保这一点

<div id="my_element"></div>

<script>
    var element = document.getElementById('my_element');
</script>

在这种情况下,你也可以把代码放在body结束标记(</body>)之前(所有DOM元素在脚本执行时都是可用的)。

其他解决方案包括监听load [MDN]或DOMContentLoaded [MDN]事件。在这些情况下,将JavaScript代码放在文档中的什么位置并不重要,只需记住将所有DOM处理代码放在事件处理程序中即可。

例子:

window.onload = function() {
    // process DOM elements here
};

// or

// does not work IE 8 and below
document.addEventListener('DOMContentLoaded', function() {
    // process DOM elements here
});

有关事件处理和浏览器差异的更多信息,请参阅quirksmode.org上的文章。

jQuery

首先确保正确加载了jQuery。使用浏览器的开发工具来找出jQuery文件是否被找到,如果没有,就纠正URL(例如,在开头添加http:或https:方案,调整路径等)。

监听load/DOMContentLoaded事件正是jQuery使用.ready() [docs]所做的事情。所有影响DOM元素的jQuery代码都应该在该事件处理程序中。

事实上,jQuery教程明确指出:

当使用jQuery时,我们所做的几乎所有事情都是读取或操作文档对象模型(DOM),我们需要确保一旦DOM准备好,我们就开始添加事件等。

为此,我们为文档注册一个就绪事件。 $(文档)时函数(){

   // do stuff when DOM is ready
});

或者你也可以使用简写语法:

$(function() {
    // do stuff when DOM is ready
});

两者是等价的。