为什么jQuery或像getElementById这样的DOM方法找不到元素?
document.getElementById
, $("#id")
或任何其他DOM方法/ jQuery选择器未找到元素的可能原因是什么?
示例问题包括:
jQuery默默无法绑定事件处理程序,并且返回null
的标准DOM方法导致错误:
Uncaught TypeError:无法设置null的属性'...'
当您的脚本运行时,您尝试查找的元素不在DOM中。
您的DOM依赖脚本的位置可能会对其行为产生深远影响。 浏览器从上到下解析HTML文档。 元素被添加到DOM并且脚本(通常)在遇到时执行。 这意味着订单很重要。 通常,脚本无法找到标记后面出现的元素,因为这些元素尚未添加到DOM中。
考虑以下标记; 脚本#1在脚本#2成功时未能找到<div>
:
<script>
console.log("script #1: %o", document.getElementById("test")); // null
</script>
<div id="test">test div</div>
<script>
console.log("script #2: %o", document.getElementById("test")); // <div id="test" ...
</script>
简而言之:因为您正在查找的元素在文档中尚不存在(尚)。
对于这个答案的其余部分,我将使用getElementById
作为示例,但同样适用于getElementsByTagName
, querySelector
和任何其他选择元素的DOM方法。
可能的原因
元素可能不存在有两个原因:
具有传递的ID的元素实际上不存在于文档中。 您应该仔细检查您传递给getElementById
的ID是否与(生成的)HTML中现有元素的ID真正匹配,并且您没有拼错ID(ID区分大小写!)。
顺便提一下,在大多数实现querySelector()
和querySelectorAll()
方法的当代浏览器中,CSS样式表示法用于通过其id
检索元素,例如: document.querySelector('#elementID')
,而不是在document.getElementById('elementID')
下通过id
获取元素的方法; 在第一个#
字符是必不可少的,在第二个它会导致该元素不被检索。
您调用getElementById
时,该元素不存在。
后一种情况很常见。 浏览器从上到下分析和处理HTML。 这意味着在DOM元素出现在HTML之前发生的对DOM元素的任何调用都将失败。
考虑下面的例子:
<script>
var element = document.getElementById('my_element');
</script>
<div id="my_element"></div>
该div
出现在script
。 在脚本执行的那一刻,元素还不存在, getElementById
将返回null
。
jQuery的
这同样适用于所有使用jQuery的选择器。 如果拼写错误,或者您试图在实际存在之前选择它们,jQuery将无法找到元素。
另外一个转折点是当jQuery没有找到,因为你已经加载了没有协议的脚本并且正在从文件系统运行:
<script src="//somecdn.somewhere.com/jquery.min.js"></script>
此语法用于允许脚本通过HTTPS在协议https://的页面上加载,并使用协议http://在页面上加载HTTP版本
它具有尝试和未能加载file://somecdn.somewhere.com...
的不幸副作用file://somecdn.somewhere.com...
解决方案
在调用getElementById
(或任何DOM方法)之前,请确保您要访问的元素存在,即DOM已加载。
这可以通过简单地将JavaScript放在相应的DOM元素之后来保证
<div id="my_element"></div>
<script>
var element = document.getElementById('my_element');
</script>
在这种情况下,您还可以将代码放在关闭主体标记( </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准备好后立即开始添加事件等。
为此,我们为文档注册一个准备好的事件。
$(document).ready(function() {
// do stuff when DOM is ready
});
或者,您也可以使用简写语法:
$(function() {
// do stuff when DOM is ready
});
两者都是相同的。
基于ID的选择器不起作用的原因
解决方案
尝试在声明后访问元素,或者使用像$(document).ready();
这样的东西$(document).ready();
对于来自Ajax响应的元素,请使用jQuery的.bind()
方法。 老版本的jQuery具有.live()
。
使用工具[例如浏览器的webdeveloper插件]查找重复的ID并将其删除。
上一篇: Why does jQuery or a DOM method such as getElementById not find the element?