无法读取null的属性“ addEventListener”


105

我必须在项目中使用香草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;
};

我该如何处理?我可能需要将所有代码都包装在另一个函数中,或者使用if / else语句,以便仅在特定页面上搜索ID,但不能完全确定。


1
您可以显示html代码吗?似乎找不到ID为'overlayBtn'的元素
BlaShadow 2014年

2
在这些函数无法找到ID的页面上,我收到“无法读取属性'addEventListener'为null”的错误,其他函数均无效。我认为答案几乎就是这个问题。您找不到元素,因此无法向其添加事件侦听器...
Etai 2014年

1
如果您class在html中使用而不是在脚本中id调用a getElementById,就可能发生这种情况。
Deke 2016年

Answers:


196

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

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

太棒了 做到了。我也将onclick函数移到了if语句中。我在下面发布了最终代码。
morocklo 2014年

3
这将是null在React组件未安装之前!

谢谢男人:D正是我想要的...。我的应用程序中有多个侦听器,并且这些侦听器分散在不同的视图中。如果页面上存在该元素,则表明我在处理JS
VegaStudios,

非常有用,谢谢!
sc_props

113

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

如果您将这行代码放在

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

23

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


1
是的,我认为根据情况有多种解决方案。
rpeg

16

我遇到了同样的错误,但是执行null检查似乎没有帮助。

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

document.addEventListener('DOMContentLoaded', function () {
    el.addEventListener('click', swapper, false);
});

我认为这是因为我使用的框架(Angular)正在动态更改HTML类和ID。


1
在玩电子游戏时,我遇到了同样的问题。使用相同的方法保存。
查尔斯

9

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

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



5

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

<html>
    <body>
        .........
        <script src="main.js"></script>
    </body>
</html>

3

感谢@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;
  };
}

2

我只是在脚本标记中添加了“异步”,这似乎已经解决了该问题。我不确定为什么,如果有人可以解释,但这对我有用。我的猜测是页面没有等待脚本加载,因此页面与JavaScript同时加载。

异步/等待使我们能够以同步方式编写异步代码。它只是使用生成器和yield语句来“暂停”执行的语法糖,使我们能够将其分配给变量!

这是参考链接-https : //medium.com/siliconwat/how-javascript-async-await-works-3cab4b7d21da


2

我遇到了同样的问题,并检查了null,但没有帮助。因为脚本是在页面加载之前加载的。因此,只需将脚本放在end body标签之前即可解决该问题。


0

正如其他人所说的那样,问题在于脚本是在页面(尤其是目标元素)加载之前执行的。

但是我不喜欢重新排序内容的解决方案。

首选的解决方案是将事件处理程序放在页面上的onload事件上,然后在此处设置侦听器。这将确保在执行分配之前加载页面和目标元素。例如

    <script>
    function onLoadFunct(){
            // set Listener here, also using suggested test for null
    }
    ....
    </script>

    <body onload="onLoadFunct()" ....>
    .....

0

我有一些引号和名字。我正在使用“更新”按钮来更新与特定名称相关联的最后一个引号,但是单击“更新”按钮后它并没有更新。我在下面包含server.js文件和外部js文件(main.js)的代码。

main.js(外部js)

var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})var update = document.getElementById('update');
if (update){
update.addEventListener('click', function () {

  fetch('quotes', {
  method: 'put',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({
    'name': 'Muskan',
    'quote': 'I find your lack of faith disturbing.'
  })
})
.then(res =>{
    if(res.ok) return res.json()
})
.then(data =>{
    console.log(data);
    window.location.reload(true);
})
})
}

server.js文件

app.put('/quotes', (req, res) => {
  db.collection('quotations').findOneAndUpdate({name: 'Vikas'},{
    $set:{
        name: req.body.name,
        quote: req.body.quote
    }
  },{
    sort: {_id: -1},
    upsert: true
  },(err, result) =>{
    if (err) return res.send(err);
    res.send(result);
  })

})

0

非常感谢,在您使用的特定页面中加载脚本,而不是在所有页面中加载脚本,有时使用swiper.js或其他库可能会导致此错误消息,这是解决此问题的唯一方法,是在特定页面上加载JS库该ID存在,并阻止在所有页面中加载相同的库。

希望这对您有所帮助。


0

我遇到了同样的问题,但是我的身份证已经出现。所以我尝试添加“ window.onload = init;” 然后,我用一个init函数包装了原始的JS代码(称其为您想要的)。这行得通,因此至少就我而言,我在加载文档之前添加了一个事件侦听器。这也可能是您正在经历的。


-1

这是因为在执行bundle js时尚未加载该元素。

我会将其移到文件的<script src="sample.js" type="text/javascript"></script>最底部index.html。这样,您可以确保在解析和呈现所有html元素之后执行脚本。


不正确 这是老派思想。如您所述,最后加载会延迟加载,但不能确保DOM已完全绘制。使用hack的旧页面无法运行,因为DOM绘制比加载慢。此答案 可确保在执行之前绘制DOM。
Machavity

-3

窗口加载时添加所有事件侦听器。无论放置脚本标签在哪里,都可以像超级按钮一样工作。

window.addEventListener("load", startup);

function startup() {

  document.getElementById("el").addEventListener("click", myFunc);
  document.getElementById("el2").addEventListener("input", myFunc);

}

myFunc(){}

页面的绘制有时可能比脚本的加载花费更长的时间,因此在所有情况下位置都不是那么重要。添加侦听器是首选方法,但load出于相同原因也已弃用。首选使用DOMContentLoaded,因为它仅在完全绘制DOM之后才触发。
Machavity

谢谢,我会尽力的。我从Mozilla网络获得了答案。我认为这是一个值得信赖的消息来源。
Natalie Jimenez
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.