为什么jQuery或者像getElementById这样的DOM方法找不到元素?

document.getElementById$("#id")或任何其他DOM方法/ jQueryselect器没有find元素的可能原因是什么?

示例问题包括:

jQuery默默无法绑定事件处理程序,而标准DOM方法返回null导致错误:

Uncaught TypeError:无法设置null的属性“…”

当您的脚本运行时,您尝试查找的元素不在DOM中 。

您的DOM依赖脚本的位置可能会对其行为产生深远的影响。 浏览器从上到下parsingHTML文档。 元素被添加到DOM中,脚本(通常)在遇到时执行。 这意味着订单很重要。 通常情况下,脚本无法find标记后面出现的元素,因为这些元素尚未添加到DOM中。

考虑以下标记; 脚本#1在脚本#2成功时未能find<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作为示例,但同样适用于getElementsByTagNamequerySelector和任何其他select元素的DOM方法。

可能的原因

元素可能不存在有两个原因:

  1. 具有通过ID的元素实际上不存在于文档中。 您应该仔细检查您传递给getElementById的ID是否与(生成的)HTML中现有元素的ID真正匹配,并且您没有拼错 ID(ID 区分大小写 !)。

    顺便说一下,在大多数实现querySelector()querySelectorAll()方法的当代浏览器中 ,CSS样式表示法用于通过其id检索元素,例如: document.querySelector('#elementID') ,而不是document.getElementById('elementID')下通过id获取元素的方法; 在第一个#字符是必不可less的,在第二个将导致该元素不被检索。

  2. 您调用getElementById 时,该元素不存在。

后一种情况很常见。 浏览器从上到下分析和处理HTML。 这意味着任何在DOM元素出现之前出现在DOM元素上的调用都将失败。

考虑下面的例子:

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

div出现 script 。 在脚本执行的那一刻,元素还不存在, getElementById将返回null

jQuery的

这同样适用于所有使用jQuery的select器。 如果拼写错误,或者在实际存在之前尝试select它们 jQuery将无法find元素。

添加扭曲是当没有findjQuery,因为你已经加载脚本没有协议,并从文件系统运行:

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

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

它有不幸的副作用尝试和无法加载file://somecdn.somewhere.com...


解决scheme

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

这可以通过简单地把你的JavaScript放在相应的DOM元素之后来保证

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

在这种情况下,您还可以将代码放在closures主体标记( </body> )之前(所有DOM元素在脚本执行时都可用)。

其他解决scheme包括监听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已正确加载。 使用浏览器的开发人员工具来查找是否find了jQuery文件,如果不是,请更正URL(例如,在开头添加http:https:scheme,调整path等)

监听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的select器不工作的原因

  1. 指定了id的元素/ DOM尚不存在。
  2. 该元素存在,但它没有在DOM中注册[在Ajax响应中dynamic附加HTML节点的情况下]。
  3. 存在多个具有相同ID的元素,这是导致冲突的原因。

解决scheme

  1. 尝试在声明后访问元素,或者使用像$(document).ready();这样的东西$(document).ready();

  2. 对于来自Ajax响应的元素,请使用jQuery的.bind()方法。 老版本的jQuery具有.live()

  3. 使用工具[例如浏览器的web开发者插件]查找重复的id并将其删除。

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

但是,现代开发实践经常可以使用DocumentFragments操作文档树之外的文档元素,或者直接简单地分离/重新附加当前元素。 这些技术可以用作JavaScript模板的一部分,或者避免过多的重绘/回stream操作,而这些元素正在被严重改变。

同样,在现代浏览器中推出的新“Shadow DOM”function允许元素成为文档的一部分,但不能通过document.getElementById及其所有同级方法(querySelector等)进行查询。 这是为了封装function并专门隐藏它。

不过,再一次,你正在寻找的元素很可能还没有在文档中,你应该按照Felix的build议去做。 但是,您也应该意识到,越来越多的元素不是唯一的原因,可能是暂时的或永久的。

如果您尝试访问的元素位于iframe并且您尝试在iframe的上下文之外访问该元素,则也会导致失败。

如果你想获得一个iframe元素,你可以在这里find。

我只是在努力,并分享以防万一它是有用的。

即使当我使用debugging器,并发现在运行时已经存在的项目,没有明显的原因,为什么控制台logging(并落下)与未定义。

最后我重写了这段代码。 我没有拼错,但我想我已经把“身份证”的D字母大写了。 现在效果很好。