提问人:William S 提问时间:7/4/2022 最后编辑:Shachar297William S 更新时间:7/4/2022 访问量:475
为什么当我在遍历 DOM 时使用节点列表或 HTML 集合中的元素时,我会变得未定义?
Why do I get undefined when I use elements from a node-list or HTML-Collection when traversing the DOM?
问:
在遍历 DOM 时,有时会在一个父元素下有许多子元素。
我可以使用 a 将这些子项作为节点列表获取,也可以使用 .querySelectorAll
element.children
但是当我选择一个用于放入我的 DOM 树遍历时,我得到 .undefined
我尝试将节点列表和HTML集合转换为数组并以这种方式使用它们,但没有成功。我尝试使用常规for循环和foreach循环来选择单个元素,但总是失败。undefined
我创建了一个虚构的情况来显示这种情况,尽管问题无需遍历 DOM 即可解决,但您必须想象这是必要的。
- [HTML全文]
<!DOCTYPE html>
<html lang="en">
<head>
<title>Testing</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="eric_meyer_reset_2.css" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="wrapper">
<div id="topOfPage">
<header>
<h1>Random Number Generator</h1>
</header>
<div id="simulated RNG">
<p>Your number is: <span id="theRandomNumber">2</span></p>
<button type="button" id="prizeOpenButton">Press for Prize</button>
</div>
</div>
<div id="bottomOfPage">
<!-- These sections are added dynamically during the script operation -->
<section class="joy" data-id="0">Hurray</section>
<section class="joy" data-id="1">Hurrah</section>
<section class="joy" data-id="2">Yay</section>
<section class="joy" data-id="3">Congrats</section>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
- CSS的
.joy {
display: none
}
- JavaScript的
const randomNumber = document.getElementById("theRandomNumber");
const prizeButton = document.getElementById("prizeOpenButton")
let matchNumberToPrizeSection = function (event) {
let prizeSections = document.querySelectorAll(".joy");
let theSection = null;
for (let i = 0; i < prizeSections.length; i++) {
if (prizeSections[i].dataset.id === randomNumber) {
theSection = prizeSections[i];
}
}
// lets say for some reason we have to traverse the DOM
// starting with the button going to the "theSection" above
let winningSection = event.target.parentElement.parentElement.nextElementSibling.theSection;
console.log(winningSection.innerHTML);
}
prizeButton.addEventListener("click", matchNumberToPrizeSection);
答:
0赞
PsiKai
7/4/2022
#1
我看到了许多问题,但以下代码有效。
首先,您正在比较元素,而不是元素的文本或 data-id。我仔细检查并清理了那里的不一致之处。
- 这是返回一个元素
const randomNumber = document.getElementById("theRandomNumber");
- 但是您正在将其与数字进行比较.他们永远不会匹配
dataset.id
if (prizeSections[i].dataset.id === randomNumber)
let winningSection = event.target.parentElement.parentElement.nextElementSibling.theSection
- 该变量指向一个元素,而该元素不是 的属性。我想进行元素链接并搜索作为 的子元素,然后调用它并传入 id 或类或其他任何内容
theSection
nextElementSibling
nextElementSibling
querySelector
let winningSection = event.target.parentElement.parentElement.nextElementSibling.querySelector([`data-id="${theSection.dataset.id}"`])
在此示例中,上述内容是多余的,我认为没有理由像您那样遍历 DOM。这是创建 bug 的简单方法,尤其是在您四处移动或向标记添加项目时。
由于您拥有 ,因此可以查询整个文档以查找该 ID。这将在将来对 DOM 的更改中得到强化。data-id
const randomNumber = document.getElementById("theRandomNumber").innerText;
const prizeButton = document.getElementById("prizeOpenButton")
let matchNumberToPrizeSection = function (event) {
let prizeSections = document.querySelectorAll(".joy");
let theSection = null;
for (let i = 0; i < prizeSections.length; i++) {
if (prizeSections[i].dataset.id === randomNumber) {
theSection = prizeSections[i].dataset.id;
}
}
let winningSection = document.querySelector(`[data-id="${theSection}"]`);
console.log(winningSection.innerHTML);
}
prizeButton.addEventListener("click", matchNumberToPrizeSection);
.joy {
display: none
}
<div id="wrapper">
<div id="topOfPage">
<header>
<h1>Random Number Generator</h1>
</header>
<div id="simulated RNG">
<p>Your number is: <span id="theRandomNumber">2</span></p>
<button type="button" id="prizeOpenButton">Press for Prize</button>
</div>
</div>
<div id="bottomOfPage">
<!-- These sections are added dynamically during the script operation -->
<section class="joy" data-id="0">Hurray</section>
<section class="joy" data-id="1">Hurrah</section>
<section class="joy" data-id="2">Yay</section>
<section class="joy" data-id="3">Congrats</section>
</div>
</div>
评论
0赞
William S
7/4/2022
这样做的全部原因是想象必须遍历 DOM 并解决我的问题。这只是一个虚构的问题。我可以给你我的真实代码,但它很长。问题是每次我尝试遍历 DOM 并且必须使用节点列表或 HTML 集合中的元素时,我都会得到未定义。
0赞
PsiKai
7/4/2022
好的,这很好,无论如何,你遍历 DOM 似乎与你变得未定义的原因分开。我提到了一些不一致之处。我将更新我的答案以专门指出它们。
0赞
Bergi
7/4/2022
目前尚不清楚您为什么更改为 ,它只是将 分配给 。当然,可以只用 [data-id=“${randomNumber}”] 替换整个循环,但我认为这不是 OP 的重点。theSection = prizeSections[i];
theSection = prizeSections[i].dataset.id;
randomNumber
theSection
const theSection = document.querySelector(
);
0赞
PsiKai
7/4/2022
@Bergi在这个代码示例中有很多可以重构的地方,但就我而言,OP 遇到的问题不是基于节点列表或基于 HTML 集合的。我进行了更新以提高清晰度。
0赞
William S
7/4/2022
再次感谢PsiKai。如果你自己在一个更好的例子中尝试,那就没问题了。我坚持这样一个事实,即在尝试遍历 DOM 时,您无法使用节点列表或 HTML 集合中的元素。这是我的问题,我为事实证明是一个糟糕的例子问题道歉。
0赞
William S
7/4/2022
#2
虽然在构建 DOM 遍历时不能直接或间接使用 node-list 或 HTML-Collection 元素。我最终发现,我可以在许多子元素之前使用该元素,在我最初的问题中,该元素的 id 为 bottomOfPage。我所要做的是使用 node-list 元素找到我需要的子元素的索引,并在父元素中使用该索引,如下所示。div
div
event.target.parentElement.parentElement.nextElementSibling.children(index)
评论
winningSection