无法读取 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 加载之前加载。可以有两种解决方案:
-
将脚本标签放在正文结束标签 (
</body>
) 之前。
将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 时该元素尚未加载。
我会将<script src="sample.js" type="text/javascript"></script>
移动到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 的属性(读取“添加”)