【问题标题】:Cannot read property 'addEventListener' of null无法读取 null 的属性“addEventListener”
【发布时间】:2014-11-24 06:32:25
【问题描述】:

我必须在一个项目中使用原生 JavaScript。我有一些功能,其中一个是打开菜单的按钮。它适用于目标 id 存在的页面,但会在 id 不存在的页面上导致错误。在函数找不到 id 的那些页面上,我收到“无法读取属性 '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,但不确定。

【问题讨论】:

  • 你能显示html代码吗?似乎找不到 id 为“overlayBtn”的元素
  • 在函数找不到 id 的页面上,我收到“无法读取属性 'addEventListener' of null ”错误,并且我的其他函数都不起作用。我认为答案几乎就在问题中。您找不到该元素,因此无法向其添加事件侦听器...
  • 如果您在 html 中使用了 class 而不是 id 并且您在脚本中调用了 getElementById,则很容易发生这种情况。
  • 刚刚遇到addEventListener could be null 的类似问题。在<body/> 标签之后移动<script src="..."></script> 似乎可以解决这个问题。
  • @Reborn 我收到这个错误很久了。这解决了它。

标签: javascript function getelementbyid addeventlistener


【解决方案1】:

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

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

【讨论】:

  • 太棒了。那成功了。我还将 onclick 函数移到该 if 语句中。我在下面发布了最终代码。
  • 在 react 组件挂载之前将是 null
  • 谢谢 :D 正是我想要的……我的应用程序中有多个听众,听众分布在不同的视图中。如果页面上存在该元素,则说明我的 JS 搞砸了
  • 我已将此方法与以下stackoverflow.com/a/1760268/5923833 结合使用以解决此错误的问题。在我的情况下,错误的触发器是点击页面的输入或重新加载,然后将选项卡更改为另一个页面。现在,使用您的代码和其他解决方案,我能够防止页面加载错误,然后在用户返回选项卡时添加事件侦听器。
  • Insted 在 之后移动
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 是的,我认为这个问题有多种解决方案,具体取决于场景。
    • 正确答案。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

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

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

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

      【讨论】:

        【解决方案6】:

        将脚本放在正文标签的末尾。

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

            1. 将脚本标签放在正文结束标签 (&lt;/body&gt;) 之前。
            2. async 关键字添加到您的脚本标签中。

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

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

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

            我更喜欢第二个选项。阅读有关异步和延迟的更多信息here

            【讨论】:

            • 你完全正确。我添加了异步并且错误消息停止了
            【解决方案9】:

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

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

            在我看来更具可读性和简洁性。

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

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

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

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

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

                【讨论】:

                  【解决方案12】:

                  我遇到了同样的问题,但我的 id 存在。所以我尝试添加“window.onload = init;”然后我用一个 init 函数包装了我的原始 JS 代码(你可以随意调用它)。这行得通,所以至少在我的情况下,我在加载文档之前添加了一个事件侦听器。这也可能是您正在经历的。

                  【讨论】:

                  • 'Doh,我在 中调用了我的 JS 文件,移到 并且它有效,您的评论帮助了我 thx
                  • 真的,你帮了我很多!
                  【解决方案13】:

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

                  【讨论】:

                    【解决方案14】:

                    您可以将属性 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>

                    Defer 是一个布尔值,指示在解析 DOM 后运行脚本

                    【讨论】:

                      【解决方案15】:

                      我有一组引号和名字。我正在使用更新按钮来更新与特定名称关联的最后一个引号,但是单击更新按钮时它没有更新。我在下面包含 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);
                        })
                      
                      })
                      

                      【讨论】:

                        【解决方案16】:

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

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

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

                        【讨论】:

                          【解决方案17】:

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

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

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

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

                          【讨论】:

                            【解决方案18】:

                            我最近遇到了这个问题,我发现我在 getElementById 和 querySelector 中提供了错误的类名。所以,我建议在你的脚本和 html 文件中交叉检查你的类和 id 名称。

                            【讨论】:

                              【解决方案19】:

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

                              我会将&lt;script src="sample.js" type="text/javascript"&gt;&lt;/script&gt; 移动到index.html 文件的最底部。这样可以确保在所有 html 元素都被解析和渲染后执行脚本。

                              【讨论】:

                              • 不正确。这是老派的想法。正如您所说,最后加载会延迟加载,但它并不能确保 DOM 完全绘制。我有使用此 hack 的旧页面无法运行,因为 DOM 绘制比加载慢。 This answer 确保在执行之前绘制 DOM。
                              • 但是@Machavity,在那个答案中,该函数也在等待DOM完全加载。那么这里有什么区别。两个答案都是对的??你能解释一下吗?
                              • @VyshakPuthusseri 他们不完全一样。您的浏览器必须加载内容,然后绘制内容 (DOM)。在大多数情况下,浏览器会按照加载顺序完成,但有时情况并非如此,在这种情况下,您的 JS 会在尝试引用未呈现的对象时中断。 DOMContentLoaded 是一个明确地让您等待浏览器先完成绘制 DOM 的事件,而不是交叉手指并希望最好的结果。
                              • 好的。明白我的错误。 @Machavity 感谢您提供这些信息。
                              【解决方案20】:

                              在窗口加载时添加所有事件侦听器。无论您将脚本标签放在哪里,都可以像魅力一样工作。

                              window.addEventListener("load", startup);
                              
                              function startup() {
                              
                                document.getElementById("el").addEventListener("click", myFunc);
                                document.getElementById("el2").addEventListener("input", myFunc);
                              
                              }
                              
                              myFunc(){}
                              

                              【讨论】:

                              • 页面的绘制有时会比脚本的加载花费更长的时间,因此位置在所有情况下都不是那么重要。添加监听器是首选方式,但出于同样的原因,load 也已被弃用。 DOMContentLoaded 是首选方式,因为它仅在 DOM 完全绘制后触发。
                              • 谢谢,我会努力的。我从 Mozilla 网络得到了答案。我认为这是一个值得信赖的来源。
                              • 此代码不响应问题。如果未找到元素(el,el2),则控制台中将显示错误。
                              猜你喜欢
                              • 2021-12-17
                              • 1970-01-01
                              • 2022-01-08
                              • 1970-01-01
                              • 1970-01-01
                              • 2020-02-06
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多