假設我有以下內容:
<div className="container">
<div id="one" class="item">
<div></div>
<div></div>
<div>
<span>foo</span>
</div>
</div>
<div id="two" class="item">
<div></div>
<div></div>
<div>
<div>foo</div>
</div>
</div>
<div id="three" class="item">
<span>foo</span>
<div></div>
<div>
<span></span>
</div>
</div>
<div id="four" class="item">
<span></span>
<div></div>
<div>
<div>
<span>foo</span>
</div>
</div>
</div>
</div>
我想回傳所有包含文本內容“foo”的跨度的專案。在上面的示例中,我希望回傳 1、2 和 4。
我寫了一個遞回方法,但在某個地方絆倒了,我想我是如何處理回傳的。這當前回傳所有專案。
const hasFoo = (el) => {
const isSpan = el.tagName?.toLowerCase() === "span";
const isMatch = el.innerText?.toLowerCase() === "foo";
if (isSpan && isMatch) {
return true;
} else if (el.children?.length) {
const nodes = [...el.children];
return nodes.forEach(node => hasFoo(node));
} else {
return false;
}
};
const container = document.getElementsByClassName("container")[0];
const nodes = [...container.children];
const filtered = nodes.filter(node => hasFoo(node));
uj5u.com熱心網友回復:
幾個問題。
className 不是類屬性的有效替代項。因此,document.getElementsByClassName("container")回傳一個空陣列。
return nodes.forEach(node => hasFoo(node))總會回來undefined的。根據 MDN(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
forEach() 對每個陣列元素執行一次 callbackFn 函式;與 map() 或 reduce() 不同,它總是回傳未定義的值并且不可鏈接。
改用 for 回圈
const hasFoo = (el) => {
const isSpan = el.tagName?.toLowerCase() === "span";
const isMatch = el.innerText?.toLowerCase() === "foo";
if (isSpan && isMatch) {
return true;
}
const nodes = [...el.children];
for (let i = 0; i < nodes.length; i ) {
if (hasFoo(nodes[i]))
return true;
}
return false;
}
uj5u.com熱心網友回復:
其他人已經指出了className和您的forEach. 但是為了更好地體驗顯式回圈,請使用Array.prototype.some,如下所示:
const hasFoo = (el) =>
(el .tagName ?.toLowerCase() === "span" && el .textContent ?.toLowerCase() === "foo") ||
[...el .children ?? []] .some (hasFoo)
const foos = [... document .querySelectorAll (".container > *")] .filter (hasFoo)
foos .forEach (div => div .classList .add ('hasFoo'))
div {border: 1px solid #ccc; margin: .125em; padding: .125em;}
span {border: 1px solid #000; padding: .125em;}
div.hasFoo {background-color: yellow; border: 2px dotted #00f;}
<div class="container"><div id="one" class="item"><div></div><div></div><div><span>foo</span></div></div><div id="two" class="item"><div></div><div></div><div><div>foo</div></div></div><div id="three" class="item"><span>foo</span><div></div><div><span></span></div></div><div id="four" class="item"><span></span><div></div><div><div><span>foo</span></div></div></div></div>
在這里,我們<div>用淺色邊框標記所有 s,<span>用深色邊框標記所有 s,并突出顯示所有具有黃色背景和虛線邊框.container的-span 的孩子。foo
uj5u.com熱心網友回復:
items它不是遞回的,但我更喜歡根據條件/要求回傳過濾后的陣列。
const items = Array.from(document.querySelectorAll('.item'));
const itemsWithFooSpans = items.filter(item => {
let hasFoo = false;
const spans = item.querySelectorAll('span');
spans.forEach(span => {
console.log('span: ', span);
if (span && span.textContent && span.textContent === 'foo') {
hasFoo = true;
}
});
return hasFoo;
});
uj5u.com熱心網友回復:
您可以首先使用簡單的目標來定位容器內的所有跨度,container.querySelectorAll("span")然后僅過濾具有正確文本內容的跨度。
獲得此串列后,您只需檢索與.item選擇器匹配的每個跨度祖先。這可以通過該Element.closest()方法來實作。
如果每個專案可能有多個這樣的跨度,您可能需要對生成的陣列進行重復資料洗掉:
const container = document.querySelector(".container");
const spans = [...container.querySelectorAll("span")]
.filter(el => el.textContent.toLowerCase() === "foo");
const items = Array.from(new Set( // avoid duplicates
spans.map(el => el.closest(".item"))
)).filter(Boolean); // avoid null
console.log(items.map(el => el.id));
<div class="container">
<div id="one" class="item">
<div></div>
<div></div>
<div>
<span>foo</span>
</div>
</div>
<div id="two" class="item">
<div></div>
<div></div>
<div>
<div>foo</div>
</div>
</div>
<div id="three" class="item">
<span>foo</span>
<div></div>
<div>
<span></span>
</div>
</div>
<div id="four" class="item">
<span></span>
<div></div>
<div>
<div>
<span>foo</span>
</div>
</div>
</div>
</div>
uj5u.com熱心網友回復:
var elem = document.querySelector(".container");
var spans = elem.querySelectorAll("span");
var found = [];
spans.forEach(item => {
if (/foo/i.test(item.textContent || "")) {
found.push({
span: item,
parent: item.closest("div.item")
});
}
})
console.log("found", found)
<div class="container">
<div id="one" class="item">
<div></div>
<div></div>
<div>
<span>foo</span>
</div>
</div>
<div id="two" class="item">
<div></div>
<div></div>
<div>
<div>foo</div>
</div>
</div>
<div id="three" class="item">
<span>foo</span>
<div></div>
<div>
<span></span>
</div>
</div>
<div id="four" class="item">
<span></span>
<div></div>
<div>
<div>
<span>foo</span>
</div>
</div>
</div>
</div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/473275.html
標籤:javascript html 递归 dom
