为什么 jQuery 或 getElementById 等 DOM 方法找不到该元素?

2023-11-25

可能的原因有哪些document.getElementById, $("#id")或者任何其他 DOM 方法/jQuery 选择器找不到元素?

示例问题包括:

  • jQuery 默默地无法绑定事件处理程序
  • jQuery“getter”方法(.val(), .html(), .text())返回undefined
  • 标准 DOM 方法返回null导致以下几个错误之一:

未捕获的类型错误:无法设置 null 的属性“...”
未捕获的类型错误:无法设置 null 的属性(设置“...”)
未捕获的类型错误:无法读取 null 的属性“...”
未捕获的类型错误:无法读取 null 的属性(读取“...”)

最常见的形式是:

未捕获的类型错误:无法将属性“onclick”设置为 null
未捕获的类型错误:无法读取 null 的属性“addEventListener”
未捕获的类型错误:无法读取 null 的属性“样式”


您试图查找的元素不在DOM当你的脚本运行时。

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

考虑以下标记;脚本 #1 找不到<div>当脚本 #2 成功时:

<script>
  console.log("script #1:", document.getElementById("test")); // null
</script>
<div id="test">test div</div>
<script>
  console.log("script #2:", document.getElementById("test")); // <div id="test" ...
</script>

那你该怎么办?您有几个选择:


选项 1:移动脚本

鉴于我们在上面的示例中看到的情况,一个直观的解决方案可能是简单地将脚本沿着标记向下移动,越过您想要访问的元素。事实上,很长一段时间以来,将脚本放在页面底部被认为是一种最佳实践由于各种原因。以这种方式组织,在执行脚本之前将解析文档的其余部分:

<body>
  <button id="test">click me</button>
  <script>
    document.getElementById("test").addEventListener("click", function() {
      console.log("clicked:", this);
    });
  </script>
</body><!-- closing body tag -->

虽然这是有道理的,并且对于旧版浏览器来说是一个可靠的选择,但它是有限的,并且有更灵活、更现代的方法可用。


选项 2:defer属性

虽然我们确实说过脚本是,“(默认情况下)在遇到它们时执行,”现代浏览器允许您指定不同的行为。如果您要链接外部脚本,则可以使用defer属性。

[defer,一个布尔属性,] 设置为向浏览器指示该脚本应在解析文档之后但在触发之前执行DOMContentLoaded.

这意味着您可以放置​​一个标记为defer任何地方,甚至<head>,并且它应该能够访问完全实现的 DOM。

<script src="https://gh-canon.github.io/misc-demos/log-test-click.js" defer></script>
<button id="test">click me</button>

请记住...

  1. defer只能用于外部脚本,即:那些具有src属性。
  2. 意识到浏览器支持,即: IE

选项 3:模块

根据您的要求,您也许可以使用JavaScript 模块。与标准脚本的其他重要区别包括(此处注明),模块会自动延迟,并且不限于外部源。

设置你的脚本type to module, e.g.:

<script type="module">
  document.getElementById("test").addEventListener("click", function(e) {
    console.log("clicked: ", this);
  });
</script>
<button id="test">click me</button>

选项 4:通过事件处理推迟

向解析文档后触发的事件添加侦听器。

DOMContentLoaded 事件

DOMContentLoaded在 DOM 从初始解析完全构建完成后触发,无需等待样式表或图像等内容加载。

<script>
  document.addEventListener("DOMContentLoaded", function(e){
    document.getElementById("test").addEventListener("click", function(e) {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

窗口:加载事件

The load事件在之后触发DOMContentLoaded并且已加载样式表和图像等其他资源。因此,它的触发时间比我们预期的要晚。不过,如果您考虑使用 IE8 等较旧的浏览器,那么支持几乎是普遍的。当然,您可能想要一个填充剂用于addEventListener().

<script>
  window.addEventListener("load", function(e){
    document.getElementById("test").addEventListener("click", function(e) {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

jQuery 的ready()

DOMContentLoaded and window:load每个人都有自己的警告。 jQuery 的ready()提供混合解决方案,使用DOMContentLoaded如果可能的话,故障转移到window:load必要时,如果 DOM 已经完成,则立即触发回调。

您可以将准备好的处理程序直接传递给 jQuery,如下所示$(handler), e.g.:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script>
  $(function() {
    $("#test").click(function() {
      console.log("clicked:", this);
    });
  });
</script>
<button id="test">click me</button>

选项 5:活动委托

将事件处理委托给目标元素的祖先。

当一个元素引发一个事件时(假设它是一个bubbling事件并且没有任何东西阻止其传播),该元素祖先中的每个父代,一直到window,也接收该事件。这允许我们将处理程序附加到现有元素,并在事件从其后代中冒出时对事件进行采样...甚至是在附加处理程序后添加的后代中。我们所要做的就是检查事件以查看它是否是由所需元素引发的,如果是,则运行我们的代码。

通常,此模式是为加载时不存在的元素保留的,或者是为了避免附加大量重复的处理程序。为了提高效率,选择目标元素最近的可靠祖先,而不是将其附加到document.

原生 JavaScript

<div id="ancestor"><!-- nearest ancestor available to our script -->
  <script>
    document.getElementById("ancestor").addEventListener("click", function(e) {
      if (e.target.id === "descendant") {
        console.log("clicked:", e.target);
      }
    });
  </script>
  <button id="descendant">click me</button>
</div>

jQuery 的on()

jQuery 通过以下方式提供此功能on()。给定事件名称、所需后代的选择器和事件处理程序,它将解析您委托的事件处理并管理您的this语境:

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<div id="ancestor"><!-- nearest ancestor available to our script -->
  <script>
    $("#ancestor").on("click", "#descendant", function(e) {
      console.log("clicked:", this);
    });
  </script>
  <button id="descendant">click me</button>
</div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 jQuery 或 getElementById 等 DOM 方法找不到该元素? 的相关文章

随机推荐