可能的原因是什么 document.getElementById
, $("#id")
或者任何其他没有找到元素的dom方法/jquery选择器?
示例问题包括:
jquery静默绑定事件处理程序失败
jquery“getter”方法( .val()
, .html()
, .text()
)返回 undefined
一种标准的dom方法 null
导致以下任何一种错误:
未捕获类型错误:无法设置null的属性“…”。未捕获类型错误:无法读取null的属性“…”
最常见的形式有:
未捕获的typeerror:无法将属性“onclick”设置为null
未捕获的typeerror:无法读取null的属性“addeventlistener”
未捕获的typeerror:无法读取null的属性“style”
6条答案
按热度按时间mutmk8jj1#
脚本运行时,您试图查找的元素不在dom中。
依赖dom的脚本的位置会对其行为产生深远的影响。浏览器从上到下解析html文档。元素被添加到dom中,脚本(通常)在遇到它们时执行。这意味着秩序很重要。通常,脚本找不到稍后出现在标记中的元素,因为这些元素尚未添加到dom中。
考虑下面的标记;脚本#1未能找到
<div>
脚本#2成功时:那么,你应该怎么做?您有几个选择:
选项1:移动脚本
将脚本进一步向下移动,就在结束正文标记之前。以这种方式组织,文档的其余部分将在执行脚本之前进行解析:
注意:将脚本放在底部通常被认为是最佳做法。
选项2:jquery的ready()
使用
$(handler)
:注意:您可以简单地绑定到
DOMContentLoaded
或window.onload
但每一个都有它的警告。jquery的ready()
提供混合解决方案。备选案文3:活动授权
委派事件的优点是,它们可以处理来自子元素的事件,这些子元素将在以后添加到文档中。
当一个元素引发一个事件时(假设它是一个冒泡事件,并且没有任何东西阻止它的传播),该元素祖先中的每个父元素也会接收该事件。这允许我们将处理程序附加到现有元素,并在事件从其子元素冒泡时对其进行采样。。。即使是附加处理程序后添加的。我们所要做的就是检查事件是否由所需元素引发,如果是,则运行代码。
jquery的
on()
为我们执行这一逻辑。我们只需提供事件名称、所需子体的选择器和事件处理程序:注意:通常,此模式是为加载时不存在的元素保留的,或者是为了避免附加大量处理程序。还值得指出的是,虽然我已经将处理程序附加到
document
(出于演示目的),您应该选择最近的可靠祖先。选项4:延迟属性
使用
defer
属性<script>
.[
defer
,一个布尔属性,]设置为向浏览器指示脚本将在解析文档后但在触发之前执行DOMContentLoaded
.以下是来自该外部脚本的代码供参考:
注:该
defer
属性看起来确实像一颗神奇的子弹,但重要的是要注意警告。。。defer
只能用于外部脚本,即:具有src
属性2.注意浏览器支持,即ie<10中的错误实现
ar7v8xwq2#
简短而简单:因为您要查找的元素在文档中还不存在。
对于这个答案的其余部分,我将使用
getElementById
例如,但这同样适用于getElementsByTagName
,querySelector
以及选择元素的任何其他dom方法。可能的原因
元素可能不存在的原因有两个:
文档中确实不存在具有传递的id的元素。您应该仔细检查您传递给的id
getElementById
确实匹配(生成的)html中现有元素的id,并且没有拼写错误(id区分大小写!)。顺便说一句,在大多数当代浏览器中
querySelector()
及querySelectorAll()
方法,css样式表示法用于按元素的id
,例如:document.querySelector('#elementID')
,而不是通过其id
在下面document.getElementById('elementID')
; 首先#
字符是必需的,在第二种情况下,它将导致无法检索元素。该元素在您调用时不存在
getElementById
.后一种情况很常见。浏览器从上到下解析和处理html。这意味着在dom元素出现在html中之前对该dom元素的任何调用都将失败。
考虑下面的例子:
这个
div
出现在script
. 在执行脚本时,元素还不存在,并且getElementById
会回来的null
.jquery
这同样适用于使用jquery的所有选择器。如果您拼错了选择器或试图在元素实际存在之前选择它们,jquery将找不到元素。
另外一个问题是,由于加载了不带协议的脚本,并且正在从文件系统运行,因此找不到jquery:
此语法用于允许脚本在协议为https://的页面上通过https加载,并在协议为http://的页面上加载http版本://
它有一个不幸的副作用,即尝试加载和未能加载
file://somecdn.somewhere.com...
解决在你打电话给
getElementById
(或任何dom方法),确保要访问的元素存在,即加载dom。这可以通过简单地将javascript放在相应的dom元素之后来确保
在这种情况下,您还可以将代码放在结束正文标记之前(
</body>
)(执行脚本时,所有dom元素都将可用)。其他解决方案包括倾听
load
[mdn]或DOMContentLoaded
[mdn]事件。在这些情况下,将javascript代码放在文档的何处并不重要,只需记住将所有dom处理代码放在事件处理程序中即可。例子:
有关事件处理和浏览器差异的更多信息,请参阅quirksmode.org上的文章。
jquery
首先确保jquery已正确加载。使用浏览器的开发人员工具确定是否找到jquery文件,如果找不到则更正url(例如,添加
http:
或https:
开始时的方案、调整路径等)倾听
load
/DOMContentLoaded
事件正是jquery所使用的.ready()
[文件]。影响dom元素的所有jquery代码都应该在该事件处理程序中。事实上,jquery教程明确指出:
当我们使用jquery读取或操作文档对象模型(dom)时,几乎所有的操作都是如此,我们需要确保在dom准备好后立即开始添加事件等。
为此,我们为文档注册一个就绪事件。
或者,您也可以使用速记语法:
两者是等价的。
iklwldmw3#
如果您试图访问的元素位于
iframe
您尝试在iframe
这也会导致它失败。如果您想在iframe中获取元素,您可以在这里了解如何获取元素。
vktxenjb4#
基于id的选择器不起作用的原因
具有指定id的元素/dom尚不存在。
元素存在,但未在dom中注册[如果是从ajax响应动态附加的html节点]。
存在多个具有相同id的元素,导致冲突。
解决
尝试在元素声明后访问该元素,或者使用
$(document).ready();
对于来自ajax响应的元素,请使用.bind()
jquery的方法。jquery的旧版本已经过时了.live()
同样的。使用工具[例如,浏览器的webdeveloper插件]查找重复ID并删除它们。
h6my8fg25#
正如@felixkling所指出的,最有可能的情况是,您正在寻找的节点不存在(目前)。
然而,现代开发实践通常可以使用documentfragments或直接分离/重新附着当前元素来操作文档树之外的文档元素。这些技术可以作为javascript模板的一部分使用,也可以在大量修改相关元素时避免过度的重新绘制/回流操作。
类似地,在现代浏览器中推出的新“影子dom”功能允许元素成为文档的一部分,但不能通过document.getelementbyid及其所有同级方法(queryselector等)进行查询。这样做是为了封装功能,特别是隐藏功能。
不过,您要查找的元素很可能(尚未)出现在文档中,您应该按照felix的建议进行操作。但是,您还应该意识到,这并不是元素不可修复(临时或永久)的唯一原因。
vpfxa7rd6#
如果脚本执行顺序不是问题所在,则问题的另一个可能原因是未正确选择元素:
getElementById
要求传递的字符串是id,而不是其他内容。如果在传递的字符串前面加上#
,并且id不以#
,将不选择任何内容:同样,对于
getElementsByClassName
,不要在传递的字符串前加前缀.
:使用queryselector、queryselectorall和jquery,要将元素与特定类名匹配,请将
.
就在上课之前。类似地,要匹配具有特定id的元素,