【问题标题】:jsdom how to get an element inside another element inside foreachjsdom如何在foreach中的另一个元素中获取一个元素
【发布时间】:2021-12-12 03:55:34
【问题描述】:

我是 JSDOM 解析器的新手。

我有以下几点:

<div id='mydiv'>
  <ul>
    <li><a title='a'>TextA</a></li>
    <li><a title='b'>TextB</a></li>
    <li><a title='c'>TextC</a></li>
    <li><a title='d'>TextD</a></li>
  </ul>
</div>

我正在使用以下代码,但无法获取文本'TextA'、'TextB'、'TextC'、'TextD'

const categoryDiv = dom.window.document.querySelectorAll('#mydiv > ul > li')
  .forEach(item => {
    console.log('item', item.getElement('a')); //not sure how to continue from here
  });
})

【问题讨论】:

  • 您的目标是记录所有链接文本还是将它们存储在 categoryDiv 中?

标签: javascript domparser


【解决方案1】:

只需使用getElementsByTagNameinnerHTML 修改您的原始代码:

const categoryDiv = dom.window.document.querySelectorAll('#mydiv > ul > li')
.forEach(item => {
   console.log('item -- ' + item.getElementsByTagName('a')[0].innerHTML); 
 });
})

【讨论】:

  • 这段代码记录了项目是对的,但如果你最终想要将文本值存储在 categoryDiv 中,.forEach 必须更改为 .map 并且 NodeList 必须转换为数组以是“可映射的”
【解决方案2】:
const categoryDiv = dom.window.document.querySelectorAll('#mydiv > ul > li')

在这第一步之后,您将拥有一个包含 4 个列表元素的 NodeList。与

console.目录(categoryDiv[0])

您可以将第一个列表对象记录到控制台并查看并期望其所有属性。有多种方法可以访问封闭的锚标记。例如

  1. .儿童 => HTML 集合
  2. .childNodes => 节点列表
  3. .getElementsByTagName('a') => HTML 集合
  4. .querySelector('a') => href 元素

只有最后一个选项直接为您提供链接元素,前三个您必须选择选择中的第一个元素才能访问链接

然后访问链接的文本有两个选项

  1. .innerHTML
  2. .textContent

在这种情况下,选择哪个并不重要,因为如果在链接上调用,两者都会在链接标签内为您提供文本。 如果在列表元素上调用它看起来像这样

listElem.outerHTML // <li><a title="a">TextA</a></li>
listElem.innerHTML  // <a title="a">TextA</a>
listElem.textContent // TextA

所以您实际上不必访问链接元素。只需在列表项上直接调用 .textContent

最后你想使用 .map 而不是 .forEach 因为 .forEach 只迭代,但不返回任何东西。 NodeList 不能直接用 .map 迭代,但可以用扩展运算符轻松转换

所以所有在一起,例如像这样

const categoryDiv = [...document.querySelectorAll('#mydiv > ul > li')]
  .map(listItem => listItem.textContent)

console.log(categoryDiv)  // ['TextA', 'TextB', 'TextC', 'TextD']

或者这个

const categoryDiv = Array.from(document.querySelectorAll('#mydiv > ul > li'), listItem => listItem.textContent)

或者甚至没有迭代的非常快速的方法是

document.querySelector('#mydiv ul')
  .textContent  // 'TextA TextB TextC TextD'
  .split(' ')  // ['TextA', 'TextB', 'TextC', 'TextD']

【讨论】:

    【解决方案3】:

    这可能很简单:

      let targets = document.querySelectorAll('#mydiv > ul > li a');
    
      for (let target of targets) {
        console.log(target.text); 
      }
    

    【讨论】:

    • 既然你省略了 li 和 a 之间的 > 我想知道......所有其他的都不是必需的,也可以省略......?
    • 其实在这种情况下你可以删除所有&gt;s; &gt; 将选择限制为父节点的直接子节点(与后代(孙子等)相反)。在这种情况下,无论如何我们都是从一个节点走到它的直接子节点,所以&gt; 不是必需的;在其他情况下 - 它可能是肯定的。
    • 我明白了,所以实际上 'ul' 和 'li' 也可以删除,在这种情况下 document.querySelectorAll('#mydiv a') 已经足够了
    • @Corrl 确实如此——在这种特殊情况下。但是,当您面对更复杂的 html 或 xml(深度嵌套的元素等)时,您应该小心选择(或跳过)哪些元素。对于更繁重的问题,您可能必须从 css 选择器切换到更强大的 xpath。这需要练习,但随着时间的推移,您会更好地了解什么时候有效。
    最近更新 更多