[英]Why do I get undefined when I use elements from a node-list or HTML-Collection when traversing the DOM?
While traversing the DOM there are sometimes many child elements under one parent.在遍历 DOM 时,有时在一个父元素下有许多子元素。
I can get these children as either node-lists using a querySelectorAll
or I can get them as HTML-Collections by using element.children
.我可以使用
querySelectorAll
将这些子节点作为节点列表获取,也可以使用element.children
将它们作为 HTML-Collections 获取。
But when I select one to use to put in my DOM tree traversal I get undefined
.但是当我选择一个用于放入我的 DOM 树遍历时,我得到
undefined
。
I have tried turning the node-lists and HTML-Collections into arrays and using them that way with no success.我尝试将节点列表和 HTML-Collections 转换为数组并以这种方式使用它们,但没有成功。 I have tried using for-of loops regular for loops and foreach loops for selecting a single element, yet always with failure
undefined
.我尝试使用 for-of 循环,常规 for 循环和 foreach 循环来选择单个元素,但总是失败
undefined
。
I have created a made up situation that shows this situation, although the problem is solvable without having to Traverse the DOM, you have to image that it is necessary.我已经创建了一个显示这种情况的虚构情况,尽管无需遍历 DOM 即可解决问题,但您必须想象这是必要的。
<!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>
.joy {
display: none
}
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);
I saw a number of issues, but the below code works.我看到了许多问题,但下面的代码有效。
For one, you were comparing elements instead of the text of the element, or the data-id.一方面,您正在比较元素而不是元素的文本或数据 ID。 I went through and cleaned up the inconsistencies there.
我通过并清理了那里的不一致之处。
const randomNumber = document.getElementById("theRandomNumber");
dataset.id
.dataset.id
进行比较。 They will never matchif (prizeSections[i].dataset.id === randomNumber)
let winningSection = event.target.parentElement.parentElement.nextElementSibling.theSection
theSection
is pointing to an element, and that is not a property of nextElementSibling
.theSection
指向一个元素,这不是nextElementSibling
的属性。 I you want to do the element chaining and search for an element that is a child of nextElementSibling
, then call querySelector
on it and pass in an id or class, or whatevernextElementSibling
子元素的元素,然后在其上调用querySelector
并传入 id 或类或其他let winningSection = event.target.parentElement.parentElement.nextElementSibling.querySelector([`data-id="${theSection.dataset.id}"`])
The above is redundant in this example, and I saw no reason to traverse the DOM like you did.以上在这个例子中是多余的,我认为没有理由像你一样遍历 DOM。 That's an easy way to create bugs, especially if you move around or add items to your markup.
这是一种创建错误的简单方法,尤其是在您四处移动或向标记添加项目时。
Since you have the data-id
, you can query the entire document for that id.由于您拥有
data-id
,因此您可以在整个文档中查询该 ID。 This will be hardened to changes to the DOM in the future.这将在未来对 DOM 的更改进行强化。
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>
While you cannot use node-list or HTML-Collection elements directly or indirectly when you are building up a DOM traversal.虽然在构建 DOM 遍历时不能直接或间接使用节点列表或 HTML-Collection 元素。 What I finally found was that I can use the element before the many child elements, in my original question that was a
div
with id of bottomOfPage.我最终发现,我可以在许多子元素之前使用该元素,在我原来的问题中是一个 id 为 bottomOfPage 的
div
。 What I had to do was find the index of the child element that I needed using the node-list elements and use that index in the parent div
like this.我必须做的是使用节点列表元素找到我需要的子元素的索引,并像这样在父
div
中使用该索引。 event.target.parentElement.parentElement.nextElementSibling.children(index)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.