javascript - JS DOM 问题:未捕获类型错误:无法读取 null 的属性“addEventListener”变为未捕获引用错误
问题描述
这是我从这里的教程中下载的代码:( https://codepen.io/Web_Cifar/pen/PoNNEYY ) 希望将其适应我正在做的事情。我把它拼凑在一起,虽然它在演示中有效(并且有一个很好的 YT 视频,他通过它),但在现场情况下它对我不起作用。我正在尝试构建一个类似于 Gravity Forms 的多页数据输入表单(GF 有一些对我不起作用的怪癖)。
我得到的第一个 Javascript 错误是:“未捕获的 TypeError:无法读取属性 'addEventListener' of null”。在 StackO 上进行研究后,我得到的一般建议是,可能尚未为我的文档加载 DOM,而在此之前我们正在调用 JS,两个建议似乎很受欢迎:1)。将您的 JS 文件移动到 HTML 文档的底部,就在您的 body 标签关闭之前(它最初在我的标签中......移动它没有任何改变)。2. 将您的 JS 函数包装在以下代码中:"window.addEventListener('DOMContentLoaded', (event) => {" 以在调用函数之前强制加载 DOM。
执行 #2 将错误更改为:ReferenceError: "changeStep" is not defined。JS 代码中有一个名为“changeStep”的函数。如果你参考上面的教程,你会发现它最初是在 JS 文件中定义的最后一个函数,所以我认为将它移到顶部会改变它。没有骰子。我已经做了一些检查,看看一些简单的 JQuery 测试是否在我的环境中工作并且它们确实有效。我对 JS 比较陌生,但我不明白为什么 DOM 不会被加载,也不明白为什么不能引用有问题的函数。
这是我的 HTML 代码的骨架:
<html>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script> /* A recommended test to see if jQuery is working, and it is. */
$(document).ready(function(){
$("button").click(function(){
alert("jQuery is working perfectly.");
});
});
</script>
<link rel="stylesheet" href="/Users/Me/Documents/multistep.css">
<body>
etc.....(moving to end of html file....)
<script type = "text/javascript" src = "/Users/Me/Documents/multistep.js" ></script>
</body>
</html>
这是我的整个 JS 脚本:
const steps = Array.from(document.querySelectorAll("form .step"));
const nextBtn = document.querySelectorAll("form .next-btn");
const prevBtn = document.querySelectorAll("form .previous-btn");
const form = document.querySelector("form");
window.addEventListener('DOMContentLoaded', (event) => {
function changeStep(btn) {
let index = 0;
const active = document.querySelector(".active");
index = steps.indexOf(active);
steps[index].classList.remove("active");
if (btn === "next") {
index++;
} else if (btn === "prev") {
index--;
}
steps[index].classList.add("active");
}
});
window.addEventListener('DOMContentLoaded', (event) => {
nextBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("next");
});
});
});
window.addEventListener('DOMContentLoaded', (event) => {
prevBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("prev");
});
});
});
window.addEventListener('DOMContentLoaded', (event) => {
form.addEventListener("submit", (e) => {
e.preventDefault();
const inputs = [];
form.querySelectorAll("input").forEach((input) => {
const { name, value } = input;
inputs.push({ name, value });
});
console.log(inputs);
form.reset();
});
});
请注意,我基本上将所有内容都包装在“window.addEventListener ...”标签中(根据上面的 Google 建议),我从引用的演示(在 codePen 中工作)中所做的唯一其他更改是将 changeStep 函数移动到文件中的第一个函数。
我不知道发生了什么。有经验的 JS 人能帮我摆脱困境吗?
解决方案
changeStep
是在第一个事件监听器的匿名回调函数中定义的,所以它只在那个函数中可见。如果要在该函数范围之外访问它,则必须在函数之外定义它,即在调用addEventListener
. 但更好的解决方案是将所有内容放在一个事件侦听器中。我看不出为什么必须要有三个。
此外,由于您仍然querySelector
在事件侦听器之外调用,它并没有解决原来的问题。这正是您在加载 DOM 上下文后想要做的事情,因此您也必须将其放入事件侦听器中。
所以解决方案是基本上把所有东西都放在一个事件监听器中:
window.addEventListener('DOMContentLoaded', (event) => {
const steps = Array.from(document.querySelectorAll("form .step"));
const nextBtn = document.querySelectorAll("form .next-btn");
const prevBtn = document.querySelectorAll("form .previous-btn");
const form = document.querySelector("form");
function changeStep(btn) {
let index = 0;
const active = document.querySelector(".active");
index = steps.indexOf(active);
steps[index].classList.remove("active");
if (btn === "next") {
index++;
} else if (btn === "prev") {
index--;
}
steps[index].classList.add("active");
}
nextBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("next");
});
});
prevBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("prev");
});
});
});
这应该回答您关于为什么会出现第二个错误的问题,但实际上将脚本放在 body 标记的末尾应该首先解决了问题,所以第一个错误可能有不同的原因。您确定您的 script 标签位于 body 标签的最后,并且您确实在 DOM 树中拥有所有要查询的元素吗?
推荐阅读
- python - 有没有办法计算两个参数的标准差和平均值?
- python - TypeError: unsupported operand type(s) for /: 'tuple' and 'int' ---不理解错误
- javascript - 如何使用 JavaScript 使用值和颜色过滤表
- node.js - TypeError:无法读取未定义的属性“nonMaxSuppressionV3Impl”
- firebase - 如何每天查询firebase并检查日期是否与当前日期相同并自动发送电子邮件?
- sql - 如何通过将相同的值添加到其他表中的 ID 来插入多行,从而创建新的对?
- bitbake - 由于 gcc-cross-x86_64-9.3.0,Poky 映像 3.1.2 失败
- ruby - 是否有可能在红宝石中使用数字名称的方法?
- javascript - javascript - 仅查找和替换匹配的右括号
- java - MPAndroidChart - 条形图未显示所有 X 轴标签