无法读取空对象的属性'addEventListener'

237

我必须在一个项目中使用纯JavaScript语言。其中有几个函数,其中一个是打开菜单的按钮。这个功能在目标id存在的页面上可以正常工作,但在没有此id的页面上会出错。在这些页面上,该函数无法找到id,我会收到“Cannot read property 'addEventListener' of 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;
};

我应该如何处理这个问题?我可能需要将这段代码全部放入另一个函数中,或者使用if/else语句,以便它仅在特定页面上搜索id,但不确定具体方法。


2
你能展示一下 HTML 代码吗?似乎找不到 ID 为 'overlayBtn' 的元素。 - BlaShadow
3
在那些无法找到id的页面上,我会收到一个“Cannot read property 'addEventListener' of null”错误,并且我的其他函数都无法工作。我认为答案基本上就在问题中了。您找不到该元素,因此无法向其添加事件侦听器... - Etai
3
如果您在HTML中使用了class而不是id,并且在脚本中调用getElementById,那么这种情况很容易发生。 - Deke
20
我遇到了类似的问题,错误提示为addEventListener可能为空(null)。将<script src="..."></script>标签移到<body/>标签后解决了这个问题。 - Malakai
@Reborn 我长时间以来一直遇到这个错误。这个方法解决了它。 - r3za
显示剩余2条评论
27个回答

360

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

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

您也可以等待代码运行直到DOMContentLoaded完成:

window.addEventListener("DOMContentLoaded", (event) => {
    const el = document.getElementById('overlayBtn');
    if (el) {
      el.addEventListener('click', swapper, false);
    }
});

2
太棒了,那解决了问题。我还把onclick函数移到了那个if语句里面。我在下面发布了最终代码。 - morocklo
4
在 React 组件挂载之前,它将为 null - user8202629
我已将此方法与 https://dev59.com/nnI-5IYBdhLWcg3wn526#1760268 结合使用,以解决该错误问题。在我的情况下,导致错误的触发器是按回车或重新加载页面,然后切换到另一页。现在,有了您的代码和其他解决方案,我能够在页面加载时防止出现错误,然后在用户返回选项卡时添加事件监听器。 - bachree
2
将<script src="..."></script>移动到<body/>之后。 - Aryan
还要检查一下你的脚本标签,它必须放在文件末尾,即在</body>标签之前。 - undefined
显示剩余2条评论

213

看起来因为执行在DOM完全加载之前,document.getElementById('overlayBtn'); 返回了 null

如果您将这行代码放在

window.onload=function(){
  -- put your code here
}

那么它将无错误地运行。

例如:

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>");
}

61

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


45

22

我遇到了同样的错误,但是进行空值检查似乎没有起到帮助作用。

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

document.addEventListener('DOMContentLoaded', function () {
    el.addEventListener('click', swapper, false);
});
我认为这是因为我正在使用一个框架(Angular),它会动态地更改我的HTML类和ID。

20
将脚本放在body标签的末尾。
<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>

12

这仅仅是因为你的JS在HTML部分加载之前就已经被加载了,所以它找不到对应的元素。只需要将整个JS代码放在一个函数中,在窗口加载时调用该函数即可。

您也可以将Javascript代码放在HTML部分之后。


10

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

  1. 将脚本标签放置在闭合body标签之前(</body>)。
  2. 在脚本标签中添加async关键字。
<script async src="script.js"></script>

使用async,文件会异步下载,下载完毕后立即执行。

我更喜欢第二个选项。有关asyncdefer的详细信息,请点击此处了解更多。


8

如果您的js代码是外部文件,请使用此方法:

<script src="filename.js" defer></script>

如果你的代码是在内部文件中,请使用 DOMContentLoaded

以上两种方式都可以确保在执行js代码之前,DOM已经完全加载!


7
这个问题已经有了答案,但针对这些简单的条件,我喜欢使用逻辑 AND(&&)运算符:
var el = document.getElementById('overlayBtn');

el && el.addEventListener('click', swapper, false);

在我看来,更易读且更简洁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接