问题描述
<div>div-1
<span>div-1-span-1
<div>div-1-span-1-div</div>
<span>div-1-span-1-span</span>
</span>
</div>
我正在尝试搜索此 DOM。我的搜索条件是innerText,即“div-1”。如果找到了innerText,那么我想将值返回为“div-1-span-1-div”和“div-1-span-1-span”,它们也是innerText。如何使用 Javascript 实现这一点。
解决方法
虽然我不确定需求背后的逻辑,但我相信以下代码似乎可以满足您的要求:
// declaring a named function that takes two arguments:
// selector: String,a CSS selector to determine the elements you're trying to search,// needle: String,a string of text that you're searching for to identify a given element:
const findElementByText = (selector,needle) => {
// here we convert the iterable NodeList returned from document.querySelectorAll()
// into an Array,using the Array.prototype.from() method:
return Array.from(
// we pass the 'selector' argument to document.querySelectorAll()
// to find all matching elements within the document:
document.querySelectorAll(selector)
// we then filter the resulting Array,using Array.prototype.filter()
// which retains,or discards,Array-elements based on truthy/falsey
// results of assessments within:
).filter(
// using the anonymous Arrow function,we retrieve the childNodes of
// each found element-node returned from document.querySelectorAll(),// 'el' is a reference to the current element-node of the Array of
// element-nodes over which we're iterating:
(el) => {
// here we declare a variable,converting the HTMLCollection returned
// by Node.childNodes into an Array of nodes in order to use Array-
// methods such as Array.prototype.some():
let children = Array.from(el.childNodes);
// we use Array.prototype.some() to test if some of the Array-elements
// match the supplied tests; if so the method returns a Boolean true
// otherwise,if no Array-element matches,it returns a Boolean false:
return children.some(
// here we use the anonymous Arrow function,and we check that some
// of the childNodes (referenced as 'child' within the function body)
// are of nodeType === 3 (a textNode) and that the childNode's nodeValue
// once trimmed of leading/trailing whitespace is equal to the
// supplied String:
(child) => child.nodeType === 3 && child.nodeValue.trim() === needle
);
// here we use Array.prototype.map() to construct a new Array based on
// the Array-elements retained by Array.prototype.filter():
}).map(
// again,using an anonymous Arrow function,passing a reference to
// the current element-node into the function:
// first we create an Array from the iterable HTMLCollection of the
// current element-node's children:
(el) => Array.from(
el.children
// we then use Array.prototype.map() to create a new Array
// based on those childNodes:
).map(
// here we create another Array from the children of the
// previous child (since you seem to explicitly want the
// child-elements of the <span> in your posted code:
(child) => Array.from(child.children)
// we then use Array.prototype.flat() to collapse the Array
// to only one-dimension:
).flat()
// and then again,we use Array.prototype.map() to map the
// textContent of each child:
.map(
(child) => child.textContent.trim()
// and finally we flatten the multidimensional Array:
).flat()
).flat();
};
console.log(findElementByText('div','div-1'));
*,::before,::after {
box-sizing: border-box;
font-size: 1rem;
line-height: 1.5;
margin: 0;
padding: 0;
}
div,span {
border: 1px solid var(--indicator);
display: block;
width: 90%;
margin: 0.2em auto;
}
div {
--indicator: lime;
}
span {
--indicator: lightblue;
}
<div>div-1
<span>div-1-span-1
<div>div-1-span-1-div</div>
<span>div-1-span-1-span</span>
</span>
</div>
参考文献: