基于innertext javascript选择元素

问题描述

    <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>

参考文献: