无法读取null的属性'addEventListener'

mor*_*klo 80 javascript function getelementbyid addeventlistener

我必须为项目使用vanilla JavaScript.我有一些功能,其中一个是打开菜单的按钮.它适用于目标ID存在的页面,但会导致id不存在的页面出错.在那些函数找不到id的页面上,我收到一个"无法读取属性'addEventListener'的null"错误,我的其他函数都没有工作.

下面是打开菜单的按钮的代码.

function swapper() {
toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
el.addEventListener('click', swapper, false);

var text = document.getElementById('overlayBtn');
text.onclick = function(){
this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
return false;
};
Run Code Online (Sandbox Code Playgroud)

我该如何处理?我可能需要将所有代码包装在另一个函数中或使用if/else语句,以便它只搜索特定页面上的id,但不确定.

Rob*_* M. 154

我认为最简单的方法el是在添加事件监听器之前检查它是否为null:

var el = document.getElementById('overlayBtn');
if(el){
  el.addEventListener('click', swapper, false);
}
Run Code Online (Sandbox Code Playgroud)

  • 在安装React组件之前,它将为“ null”! (3认同)
  • 将 <script src="..."></script> 移动到 <body/> 之后 (3认同)
  • 惊人的。这样做的伎俩。我还将 onclick 函数移到了 if 语句中。我在下面发布了最终代码。 (2认同)

Dil*_*eda 95

它似乎document.getElementById('overlayBtn');正在返回,null因为它在DOM完全加载之前执行.

如果你把这行代码放在

window.onload=function(){
  -- put your code here
}
Run Code Online (Sandbox Code Playgroud)

然后它会毫无问题地运行.

例:

window.onload=function(){
    var mb = document.getElementById("b");
    mb.addEventListener("click", handler);
    mb.addEventListener("click", handler2);
}


function handler() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-1!<br>");
}

function handler2() {
    $("p").html("<br>" + $("p").text() + "<br>You clicked me-2!<br>");
}
Run Code Online (Sandbox Code Playgroud)


Sag*_*r M 20

脚本在正文之前加载,在正文之后保留脚本


sri*_*har 18

我遇到了类似的情况.这可能是因为脚本在页面加载之前执行.通过将脚本放在页面底部,我避开了问题.

  • 是的,我认为这个问题有多种解决方案,具体取决于场景。 (2认同)

Mat*_*dor 14

我得到了同样的错误,但执行空检查似乎没有帮助.

我找到的解决方案是将我的函数包装在整个文档的事件监听器中,以检查DOM何时完成加载.

document.addEventListener('DOMContentLoaded', function () {
    el.addEventListener('click', swapper, false);
});
Run Code Online (Sandbox Code Playgroud)

我认为这是因为我使用的是一个动态改变我的HTML类和ID的框架(Angular).


小智 14

将脚本放在 body 标签的末尾。

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)


小智 11

只是因为你的 JS 在 HTML 部分之前被加载,所以它找不到那个元素。只需将整个 JS 代码放在一个函数中,该函数将在窗口加载时调用。

您还可以将 Javascript 代码放在 html 下方。


Gau*_*ngh 10

您的脚本可能放置在 HTML 的 head 标签中,并在 DOM 加载之前加载。对此可以有两种解决方案:

  1. 将脚本标记放在结束正文标记 ( ) 之前</body>
  2. async关键字添加到脚本标记中。
<script async src="script.js"></script>
Run Code Online (Sandbox Code Playgroud)

使用async,文件将被异步下载,然后在下载后立即执行。

我更喜欢第二个选择。在此处阅读有关异步和延迟的更多信息


Huy*_*yen 8

如果你的js代码是外部文件,请使用这种方式:

<script src="filename.js" defer></script>
Run Code Online (Sandbox Code Playgroud)

如果您的代码是内部文件,请使用DOMContentLoaded

上述两种方法将确保 DOM 在执行 js 代码之前完全加载!


Man*_*nel 7

这个问题已经有了答案,但我喜欢对这些简单的条件做的是使用逻辑 AND (&&) 运算符:

var el = document.getElementById('overlayBtn');

el && el.addEventListener('click', swapper, false);
Run Code Online (Sandbox Code Playgroud)

我认为更具可读性和简洁性。


小智 6

我认为最方便的方法是添加一个“?” el前加问号:

 var el = document.getElementById('overlayBtn');
 el?.addEventListener('click', swapper, false);
Run Code Online (Sandbox Code Playgroud)


mor*_*klo 5

感谢@Rob M. 的帮助。最后的代码块如下所示:

function swapper() {
  toggleClass(document.getElementById('overlay'), 'open');
}

var el = document.getElementById('overlayBtn');
if (el){
  el.addEventListener('click', swapper, false);

  var text = document.getElementById('overlayBtn');
  text.onclick = function(){
    this.innerHTML = (this.innerHTML === "Menu") ? "Close" : "Menu";
    return false;
  };
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以将属性 defer 添加到脚本标记中。您看到该错误的原因是因为脚本在 DOM 加载之前运行。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/styles.css">
    <script src="scripts/main.js" defer="defer"></script>
</head>
Run Code Online (Sandbox Code Playgroud)

Defer is a boolean value that indicates to run script once the DOM has been parsed