简体   繁体   English

无法读取 null 的属性“addEventListener”

[英]Cannot read property 'addEventListener' of null

I have to use vanilla JavaScript for a project.我必须为一个项目使用 vanilla JavaScript。 I have a few functions, one of which is a button that opens a menu.我有几个功能,其中之一是打开菜单的按钮。 It works on pages where the target id exists, but causes an error on pages where the id doesn't exist.它在目标 id 存在的页面上有效,但在 id 不存在的页面上会导致错误。 On those pages where the function cannot find the id, I receive a "Cannot read property 'addEventListener' of null " error and none of my other functions work.在 function 找不到 ID 的那些页面上,我收到“无法读取 null 的属性‘addEventListener’”错误,我的其他功能都不起作用。

Below is the code for the button that opens the menu.下面是打开菜单的按钮的代码。

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

How do I deal with this?我该如何处理? I probably need to all wrap this code in another function or use an if/else statement so that it only searches for the id on specific pages, but not sure exactly.我可能需要将此代码全部包装在另一个 function 中或使用 if/else 语句,以便它仅在特定页面上搜索 id,但不确定是否准确。

I think the easiest approach would be to just check that el is not null before adding an event listener:我认为最简单的方法是在添加事件侦听器之前检查el是否不为空:

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

It seems that document.getElementById('overlayBtn');似乎document.getElementById('overlayBtn'); is returning null because it executes before the DOM fully loads.返回null因为它在 DOM 完全加载之前执行。

If you put this line of code under如果你把这行代码放在

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

then it will run without issue.然后它将毫无问题地运行。

Example:例子:

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

I faced a similar situation.我遇到了类似的情况。 This is probably because the script is executed before the page loads.这可能是因为脚本是在页面加载之前执行的。 By placing the script at the bottom of the page, I circumvented the problem.通过将脚本放在页面底部,我绕过了这个问题。

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

I was getting the same error, but performing a null check did not seem to help.我遇到了同样的错误,但执行空检查似乎没有帮助。

The solution I found was to wrap my function inside an event listener for the whole document to check when the DOM finished loading.我找到的解决方案是将我的函数包装在整个文档的事件侦听器中,以检查 DOM 何时完成加载。

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

I think this is because I am using a framework (Angular) that is changing my HTML classes and ID's dynamically.我认为这是因为我正在使用动态更改我的 HTML 类和 ID 的框架 (Angular)。

Put script at the end of body tag.将脚本放在正文标记的末尾。

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

It's just bcz your JS gets loaded before the HTML part and so it can't find that element.只是因为您的 JS 在 HTML 部分之前被加载,所以它找不到那个元素。 Just put your whole JS code inside a function which will be called when the window gets loaded.只需将整个 JS 代码放在一个函数中,该函数将在加载窗口时调用。

You can also put your Javascript code below the html.您还可以将 Javascript 代码放在 html 下方。

This question already has an answer but what i like to do for those simple conditions is using the logical AND (&&) operator :这个问题已经有了答案,但我喜欢为那些简单的条件做的是使用逻辑 AND (&&) 运算符:

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

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

More readable and concise in my opinion.我认为更具可读性和简洁性。

Your script is probably placed in the head tag of HTML and is loading before the DOM loads.您的脚本可能位于 HTML 的 head 标记中,并且在 DOM 加载之前加载。 There can be two solutions to this:对此可以有两种解决方案:

  1. Place the script tag just before the closing body tag ( </body> ).将脚本标记放在结束正文标记 ( </body> ) 之前。
  2. Add the async keyword to your script tag.async关键字添加到您的脚本标签。

script async src="script.js"></script脚本异步 src="script.js"></script

Note : Stackoverflow is not allowing to add script tag code here for security reasons.注意:出于安全原因,Stackoverflow 不允许在此处添加脚本标记代码。 Add opening and closing parenthesis to the code above.在上面的代码中添加左括号和右括号。

With async , the file gets downloaded asynchronously and then executed as soon as it's downloaded.使用async ,文件会异步下载,然后在下载后立即执行。

I prefer 2nd option better.我更喜欢第二个选项。 Read more about async and defer here 在此处阅读有关异步和延迟的更多信息

Use this way if your js code is the external file:如果您的 js 代码是外部文件,请使用这种方式:

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

Either if your code is the internal file, use DOMContentLoaded如果您的代码是内部文件,请使用DOMContentLoaded

Two ways above will make sure that DOM fully loads before executing js code!上面两种方法可以确保 DOM 在执行 js 代码之前完全加载!

Thanks to @Rob M. for his help.感谢@Rob M. 的帮助。 This is what the final block of code looked like:这是最后一段代码的样子:

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

I had the same problem, but my id was present.我有同样的问题,但我的身份证在场。 So I tried adding "window.onload = init;"所以我尝试添加“window.onload = init;” Then I wrapped my original JS code with an init function (call it what you want).然后我用一个 init 函数包装了我的原始 JS 代码(你可以随意调用它)。 This worked, so at least in my case, I was adding an event listener before my document loaded.这行得通,所以至少在我的情况下,我在加载文档之前添加了一个事件侦听器。 This could be what you are experiencing as well.这也可能是您正在经历的。

You could add the attribute defer to your script tag.您可以将属性 defer 添加到您的脚本标签。 The reason why you're seeing that error is because the script is running before the DOM is loading.您看到该错误的原因是脚本在加载 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>

Defer is a boolean value that indicates to run script once the DOM has been parsed Defer 是一个布尔值,指示在解析 DOM 后运行脚本

I encountered the same problem and checked for null but it did not help.我遇到了同样的问题并检查了 null 但它没有帮助。 Because the script was loading before page load.因为脚本是在页面加载之前加载的。 So just by placing the script before the end body tag solved the problem.因此,只需将脚本放在 end body 标记之前即可解决问题。

I've a collection of quotes along with names.我有一组引号和名字。 I'm using update button to update the last quote associated with a specific name but on clicking update button it's not updating.我正在使用更新按钮来更新与特定名称关联的最后一个引号,但是单击更新按钮时它没有更新。 I'm including code below for server.js file and external js file (main.js).我在下面包含 server.js 文件和外部 js 文件(main.js)的代码。

main.js (external 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 file 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);
  })

})

I simply added 'async' to my script tag, which seems to have fixed the issue.我只是在我的脚本标签中添加了“异步”,这似乎解决了这个问题。 I'm not sure why, if someone can explain, but it worked for me.我不确定为什么,如果有人可以解释,但它对我有用。 My guess is that the page isn't waiting for the script to load, so the page loads at the same time as the JavaScript.我的猜测是页面没有等待脚本加载,因此页面与 JavaScript 同时加载。

Async/Await enables us to write asynchronous code in a synchronous fashion. Async/Await 使我们能够以同步方式编写异步代码。 it's just syntactic sugar using generators and yield statements to “pause” execution, giving us the ability to assign it to a variable!它只是使用生成器和 yield 语句来“暂停”执行的语法糖,让我们能够将其分配给变量!

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

As others have said problem is that script is executed before the page (and in particular the target element) is loaded.正如其他人所说的那样,问题是脚本在页面(特别是目标元素)加载之前执行。

But I don't like the solution of reordering the content.但我不喜欢重新排序内容的解决方案。

Preferred solution is to put an event handler on page onload event and set the Listener there.首选的解决方案是在页面 onload 事件上放置一个事件处理程序并在那里设置监听器。 That will ensure the page and the target element is loaded before the assignment is executed.这将确保在执行分配之前加载页面和目标元素。 eg例如

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

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

I got this issue recently, and I found I was providing a wrong classname in getElementById and querySelector.我最近遇到了这个问题,我发现我在 getElementById 和 querySelector 中提供了错误的类名。 So, I will suggest to also cross-check your class and id names in your script and html file.所以,我建议还要在你的脚本和 html 文件中交叉检查你的类和 id 名称。

I faced this problem when I tried to get an element by Id which was a class.当我试图通过 Id 获取一个类元素时,我遇到了这个问题。 Check and confirm that the your getting the element by the correct attribute eg id or class.检查并确认您通过正确的属性(例如 id 或类)获取元素。 else you will have this error否则你会有这个错误

This error also happens when the "element is not present in the DOM" or when the id or classname doesn't exist but you are asking for it in the scripts file.当“DOM 中不存在元素”或idclassname不存在但您在脚本文件中要求它时,也会发生此错误。 Hence, you are calling an event on null.因此,您在 null 上调用事件。

I think the most accessible approach would be to add a '?'我认为最方便的方法是添加一个“?” question mark before el: el前面的问号:

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

This is because, people have habit of defining their javascript file in the head itself, So when you do something in html tags than your javscript file is executed first than your html file so the value returned is NULL . This is because, people have habit of defining their javascript file in the head itself, So when you do something in html tags than your javscript file is executed first than your html file so the value returned is NULL .

Solution: Define your Javascript file at the end of your bodytag`;解决方案: Define your Javascript file at the end of your

I think the easiest approach is to use defer.我认为最简单的方法是使用 defer。 Don't know why no one posted this answer-不知道为什么没有人发布这个答案-

<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>
<script src="style.js" defer></script>
</head>

This worked for me even on vue.js component called "myCardButton":即使在名为“myCardButton”的 vue.js 组件上,这也对我有用:

<script>
    document.addEventListener('readystatechange', event => {
        if(document.getElementById("myCardButton"))
        document.getElementById("myCardButton").addEventListener("click", myFunction, false);
    });

    function myFunction() {
        alert("hello")
    }
    
    if(document.getElementById("myCardButton") !== null)
        document.getElementById("myCardButton").removeEventListener('click',myFunction)
 
</script>

using optional chaining operator (?.) will return an undefined on pages the element doesn't exist instead of throwing an error.使用可选的链接运算符 (?.) 将在元素不存在的页面上返回 undefined 而不是抛出错误。 example;例子;

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

This is because the element hadn't been loaded at the time when the bundle js was being executed.这是因为在执行 bundle js 时该元素尚未加载。

I'd move the <script src="sample.js" type="text/javascript"></script> to the very bottom of the index.html file.<script src="sample.js" type="text/javascript"></script>移动到index.html文件的最底部。 This way you can ensure script is executed after all the html elements have been parsed and rendered .这样,您可以确保在所有 html 元素都被解析和渲染后执行脚本。

Add all event listeners when a window loads.Works like a charm no matter where you put script tags.在窗口加载时添加所有事件侦听器。无论您将脚本标签放在哪里,都可以像魅力一样工作。

window.addEventListener("load", startup);

function startup() {

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

}

myFunc(){}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM