无法读取 null 的属性“addEventListener”

Posted

技术标签:

【中文标题】无法读取 null 的属性“addEventListener”【英文标题】:Cannot read property 'addEventListener' of null 【发布时间】: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 我收到这个错误很久了。这解决了它。 【参考方案1】:

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

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

【讨论】:

太棒了。那成功了。我还将 onclick 函数移到该 if 语句中。我在下面发布了最终代码。 在 react 组件挂载之前将是 null 谢谢 :D 正是我想要的……我的应用程序中有多个听众,听众分布在不同的视图中。如果页面上存在该元素,则说明我的 JS 搞砸了 我已将此方法与以下***.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 加载之前加载。可以有两种解决方案:

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

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

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

使用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),则控制台中将显示错误。

以上是关于无法读取 null 的属性“addEventListener”的主要内容,如果未能解决你的问题,请参考以下文章

无法读取 null 的属性“图像”

测试无法读取 null 的属性 InnerHTML

未捕获的类型错误:无法读取 null 的属性(读取“添加”)

如何调试错误“无法读取 null 的属性”

未捕获的类型错误无法读取 null 的属性(读取“查询选择器”)

TypeError:无法读取 null 的属性(读取“classList”)