无法读取null的属性'addEventListener'

时间:2014-09-29 19:11:31

标签: 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;
};

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

19 个答案:

答案 0 :(得分:139)

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

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

答案 1 :(得分:80)

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

答案 2 :(得分:16)

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

答案 3 :(得分:12)

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

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

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

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

答案 4 :(得分:9)

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

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

答案 5 :(得分:8)

脚本在正文之前加载,脚本在内容之后

答案 6 :(得分:4)

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

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

答案 7 :(得分: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;
  };
}

答案 8 :(得分:3)

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

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

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

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

答案 9 :(得分:2)

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

答案 10 :(得分:1)

我只是将'async'添加到我的脚本标记中,这似乎解决了这个问题。我不知道为什么,如果有人可以解释,但它对我有用。我的猜测是页面没有等待加载脚本,所以页面与JavaScript同时加载。

 

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

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

答案 11 :(得分:1)

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

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

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

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

答案 12 :(得分:0)

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

希望这对您有所帮助。

答案 13 :(得分:0)

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

答案 14 :(得分: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);
  })

})

答案 15 :(得分:0)

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

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

首选解决方案是在页面onload事件上放置一个事件处理程序,并在其中设置Listener。这将确保在执行赋值之前加载页面和目标元素。例如

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

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

答案 16 :(得分:0)

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

  1. 将脚本标记放在结束正文标记 (</body>) 之前。
  2. async 关键字添加到您的脚本标记中。
<块引用>

脚本异步src="script.js">

注意:出于安全原因,Stackoverflow 不允许在此处添加脚本标记代码。在上面的代码中添加左括号和右括号。

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

我更喜欢第二个选项。详细了解异步和延迟 here

答案 17 :(得分:-1)

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

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

答案 18 :(得分:-3)

在窗口加载时添加所有事件侦听器。无论您在何处放置脚本标记,都会像魅力一样。

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}