为什么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
作为示例,但同样适用于getElementsByTagName
, querySelector
和任何其他select元素的DOM方法。
可能的原因
元素可能不存在有两个原因:
-
具有通过ID的元素实际上不存在于文档中。 您应该仔细检查您传递给
getElementById
的ID是否与(生成的)HTML中现有元素的ID真正匹配,并且您没有拼错 ID(ID 区分大小写 !)。顺便说一下,在大多数实现
querySelector()
和querySelectorAll()
方法的当代浏览器中 ,CSS样式表示法用于通过其id
检索元素,例如:document.querySelector('#elementID')
,而不是document.getElementById('elementID')
下通过id
获取元素的方法; 在第一个#
字符是必不可less的,在第二个将导致该元素不被检索。 -
您调用
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器不工作的原因
- 指定了id的元素/ DOM尚不存在。
- 该元素存在,但它没有在DOM中注册[在Ajax响应中dynamic附加HTML节点的情况下]。
- 存在多个具有相同ID的元素,这是导致冲突的原因。
解决scheme
-
尝试在声明后访问元素,或者使用像
$(document).ready();
这样的东西$(document).ready();
-
对于来自Ajax响应的元素,请使用jQuery的
.bind()
方法。 老版本的jQuery具有.live()
。 -
使用工具[例如浏览器的web开发者插件]查找重复的id并将其删除。
正如@FelixKling所指出的那样,最可能的情况是你正在寻找的节点不存在(还)。
但是,现代开发实践经常可以使用DocumentFragments操作文档树之外的文档元素,或者直接简单地分离/重新附加当前元素。 这些技术可以用作JavaScript模板的一部分,或者避免过多的重绘/回stream操作,而这些元素正在被严重改变。
同样,在现代浏览器中推出的新“Shadow DOM”function允许元素成为文档的一部分,但不能通过document.getElementById及其所有同级方法(querySelector等)进行查询。 这是为了封装function并专门隐藏它。
不过,再一次,你正在寻找的元素很可能还没有在文档中,你应该按照Felix的build议去做。 但是,您也应该意识到,越来越多的元素不是唯一的原因,可能是暂时的或永久的。
如果您尝试访问的元素位于iframe
并且您尝试在iframe
的上下文之外访问该元素,则也会导致失败。
如果你想获得一个iframe元素,你可以在这里find。
我只是在努力,并分享以防万一它是有用的。
即使当我使用debugging器,并发现在运行时已经存在的项目,没有明显的原因,为什么控制台logging(并落下)与未定义。
最后我重写了这段代码。 我没有拼错,但我想我已经把“身份证”的D字母大写了。 现在效果很好。
- Chrome扩展程序 – 检索Gmail的原始邮件
- 使用Javascript获取下一个/上一个元素
- .tagName和.nodeName之间的区别
- 如何将parameter passing给addEventListener监听器函数?
- find具有特定类的最接近的祖先元素
- 使用JavaScript获取选定的选项文本
- Javascript:如何dynamic创build新的div,改变它,移动它,以各种方式修改它?
- XMLparsing – ElementTree与SAX和DOM
- jQuery中width,innerWidth和outerWidth,height,innerHeight和outerHeight的区别是什么?