Javascript 为什么jQuery或getElementById之类的DOM方法找不到该元素?

Javascript 为什么jQuery或getElementById之类的DOM方法找不到该元素?,javascript,jquery,dom,Javascript,Jquery,Dom,document.getElementById、$id或任何其他DOM方法/jQuery选择器找不到元素的可能原因是什么 示例问题包括: jQuery静默绑定事件处理程序失败 jQuery getter methods.val、.html、.text返回未定义 返回null的标准DOM方法会导致以下任何错误: 未捕获的TypeError:无法将属性“…”设置为null 未捕获的TypeError:无法读取null的属性“…” 最常见的形式有: 未捕获的TypeError:无法将属性“onclic

document.getElementById、$id或任何其他DOM方法/jQuery选择器找不到元素的可能原因是什么

示例问题包括:

jQuery静默绑定事件处理程序失败 jQuery getter methods.val、.html、.text返回未定义 返回null的标准DOM方法会导致以下任何错误: 未捕获的TypeError:无法将属性“…”设置为null 未捕获的TypeError:无法读取null的属性“…”

最常见的形式有:

未捕获的TypeError:无法将属性“onclick”设置为null

未捕获的TypeError:无法读取null的属性“addEventListener”

未捕获的TypeError:无法读取null的属性“style”


脚本运行时,您试图查找的元素不在中

依赖DOM的脚本的位置会对其行为产生深远的影响。浏览器从上到下解析HTML文档。元素被添加到DOM中,脚本通常在遇到它们时执行。这意味着秩序很重要。通常,脚本找不到稍后出现在标记中的元素,因为这些元素尚未添加到DOM中

考虑以下标记;脚本1无法找到,而脚本2成功:

console.logscript 1:%o,document.getElementByIdtest;//无效的 试验室 console.logscript 2:%o,document.getElementByIdtest;// 简短而简单:因为您要查找的元素在文档中还不存在

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

可能的原因

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

文档中确实不存在具有传递的ID的元素。您应该仔细检查传递给getElementById的ID是否与生成的HTML中现有元素的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>
此语法用于允许脚本在协议为HTTPS://的页面上通过HTTPS加载,并在协议为HTTP://的页面上加载HTTP版本://

它有一个不幸的副作用,即尝试加载和未能加载file://somecdn.somewhere.com...

解决方案

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

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

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

<script>
    var element = document.getElementById('my_element');
</script>
有关事件处理和浏览器差异的更多信息,请参阅

jQuery

首先确保jQuery已正确加载。要查明是否找到jQuery文件并更正URL(如果找不到),请在开头添加http:或https:方案,调整路径等

监听load/DOMContentLoaded事件正是jQuery所做的。影响DOM元素的所有jQuery代码都应该在该事件处理程序中

事实上,报告明确指出:

当我们使用jQuery读取或操作文档对象模型DOM时,几乎所有的操作都是如此,我们需要确保在DOM准备好后立即开始添加事件等

为此,我们为文档注册一个就绪事件

$(document).ready(function() {
   // do stuff when DOM is ready
});
或者,您也可以使用速记语法:

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

两者都是等价的。

正如@FelixKling指出的,最有可能的情况是您正在寻找的节点还不存在

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

类似地,在现代浏览器中推出的新的shadowdom功能允许元素成为文档的一部分,但不能通过document.getElementById及其所有同级方法querySelector等进行查询。。这样做是为了封装 e功能,特别是隐藏它

不过,您要查找的元素很可能还没有出现在文档中,您应该按照Felix的建议进行操作。但是,您还应该意识到,这并不是元素暂时或永久不可查找的唯一原因。

基于id的选择器无法工作的原因

具有指定id的元素/DOM尚不存在。 元素存在,但未在DOM中注册[如果是从Ajax响应动态附加的HTML节点]。 存在多个具有相同id的元素,导致冲突。 解决方案

尝试在元素声明后访问该元素,或者使用$document.ready之类的东西

对于来自Ajax响应的元素,请使用jQuery的.bind方法。较旧版本的jQuery也有.live

使用工具[例如,浏览器的webdeveloper插件]查找重复ID并删除它们


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


如果要在iframe中获取元素,可以了解如何获取。

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

getElementById要求传递的字符串是ID,而不是其他内容。如果在传递的字符串前面加上前缀a,并且ID不以a开头,则不会选择任何内容:

  <div id="foo"></div>
  <div class="result"></div>
同样,对于GetElementsByCassName,不要在传递的字符串前面加前缀:

使用querySelector、querySelectorAll和jQuery,要将元素与特定类名匹配,请放置一个。就在上课之前。类似地,要将元素与特定ID匹配,请将a直接放在ID之前:

  <div class="baz"></div>
在大多数情况下,这里的规则与CSS选择器的规则相同,可以详细查看

要匹配具有两个或多个属性(如两个类名、一个类名和一个数据属性)的元素,请将每个属性的选择器放在选择器字符串中,不要用空格分隔它们,因为空格表示属性。例如,要选择:

  <div class="foo bar"></div>
使用查询字符串.foo[data bar=someData]。要选择以下选项:

您还需要确保这些方法具有正确的大小写和拼写。使用以下其中一种:

$(selector)
document.querySelector
document.querySelectorAll
document.getElementsByClassName
document.getElementsByTagName
document.getElementById
任何其他拼写或大写都不起作用。例如,document.getElementByClassName将抛出一个错误

确保将字符串传递给这些选择器方法。如果您将非字符串的内容传递给querySelector、getElementById等,则几乎肯定无法工作

如果要选择的元素上的HTML属性被引号包围,则它们必须是单引号或双引号;如果您试图按ID、类或属性进行选择,则像“或”这样的卷曲引号将不起作用


关于为什么找不到某个DOM元素,人们提出了许多问题,原因通常是JavaScript代码放在DOM元素之前。这是对这类问题的典型回答。这是社区wiki,请随意改进。是否值得修改ready事件的最后一点,以反映较新的首选语法,还是最好保持原样,以便在较旧版本中工作?对于jQuery,是否还值得添加$window.load替代方案以及$document.ready$函数{}的语法替代方案?这似乎是相关的,但感觉与你所说的有点相切。@David:使用.load的观点很好。关于语法备选方案,可以在文档中查找它们,但由于答案应该是自包含的,因此实际上可能值得添加它们。再说一次,我很确定关于jQuery的这一点已经得到了回答,可能在另一个回答中也有涉及,链接到它可能就足够了。@David:我必须修改:显然。load不推荐使用:。我不知道它是只用于图像还是也用于窗口。@大卫:不用担心,即使你不确定,你提到它也很好。我可能会添加一些简单的代码片段来显示用法。谢谢你的意见!现在是2020年-将脚本放在底部仍然被认为是最佳实践吗?我现在把所有的资源都放在浏览器上,并在脚本上使用DEDER,我不必支持不兼容的浏览器。我是一个大力提倡使用现代浏览器的人。这就是说,这种做法并没有真正花费我任何东西,它只是无处不在。另一方面,两者都有相当广泛的支持——甚至可以追溯到一些更老的浏览器版本。它们还有一个额外的优势,即清楚、明确地表示预期的行为。请记住,这些属性仅适用于指定src属性的脚本,即外部脚本。权衡利益。也许两者都用?你
我认为,这个答案还应该包括方法2中的参考。本质上,这就是这个问题的普通JS解决方案,这可能至少是一些谷歌人想知道的。@Joetje50已经在2的脚注中提到了。也就是说,这个答案最初是由主持人从jQuery特定的问题迁移而来的。因此,尽管进行了一些过渡性的编辑,它仍然带有一些这种味道。
  // Error, selected element will be undefined:
  document.getElementsByClassName('.bar')[0]
  // Fix:
  document.getElementsByClassName('bar')[0]
  <div class="baz"></div>
  // Error, selected element will be null:
  document.querySelector('baz')
  $('baz')
  // Fix:
  document.querySelector('.baz')
  $('.baz')
  <div class="foo bar"></div>
  <div class="foo" data-bar="someData"></div>
  <div class="parent">
    <span data-username="bob"></span>
  </div>
  <div class="result"></div>
  // Error, selected element will be null:
  document.querySelector('.results')
  $('.Result')
  // Fix:
  document.querySelector('.result')
  $('.result')
$(selector)
document.querySelector
document.querySelectorAll
document.getElementsByClassName
document.getElementsByTagName
document.getElementById