【问题标题】:querySelector to select the closest parent for h1 and p+p elements - is it possible?querySelector 为 h1 和 p+p 元素选择最近的父级 - 有可能吗?
【发布时间】:2018-06-22 23:26:41
【问题描述】:

编辑 结构未知 - 它应该适用于任何新闻网站,其中有一个容器/包装器,其中包含 h1 和 p+p(与该页面的主要文章相关的所有内容)

我想要的也可以实现

let story = document.querySelector('p+p').parentElement;
while(!story.querySelector('h1')){
    story = story.parentElement;
}
console.log(story);

但我想知道是否有更好的解决方案?

每篇新闻文章都有 h1 标签和带有文本的段落。我想知道是否可以编写一个 选择包含 h1 和 p+p 的最接近的父/容器元素的 querySelector。诀窍是它应该适用于任何新闻网站...


当我写作时

document.body.querySelector('* h1')

我可以获得 h1 容器,但是根据 HTML5,页面上可能有多个 h1 标签

我知道 querySelectorAll,但这对我的情况没有帮助


当我写作时

document.body.querySelector('* p+p').parentElement

我可以获得带有文本段落的文章正文的容器


我的问题是是否可以将这两个示例合并到一个查询中? (无循环和多个查询) 比如……

document.body.querySelector('* ~ h1 ~ p+p')
document.body.querySelector('* h1 p+p')

...但可行????

【问题讨论】:

  • 你还没有为此标记 jQuery。 jQuery 解决方案好吗?
  • 我现在更喜欢远离 jQuery,但如果有 jQuery 解决方案,也许它可以以某种方式移植到 vanillaJS?
  • Element#closest() 在我的情况下不起作用或者我做错了:(
  • @PatrickEvans 我在这里不举例子,因为每个人都会编写仅适用于那些提供的案例的解决方案......此外,结构是未知的 - 这是棘手的部分,但如果我的解决方案使用 while循环没问题,然后就让它去吧 - 以为我错过了一些非常简单的东西,可以在单个查询中获取它

标签: javascript html dom css-selectors selectors-api


【解决方案1】:

我创建了一个 jQuery 解决方案。

堆栈片段

$('.block').each(function(e) {
  if ($(this).find('h4').length > 0 && $(this).find('p+p').length > 0) {
    console.log('block ' + (e + 1))
  }
});
body {
  font: 13px Verdana;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="block vv">
  <h4>heading</h4>
  <p>para1</p>
  <p>para2</p>
</div>
<div class="block">
  <h4>heading</h4>
  <p>para1</p>
</div>
<div class="block">
  <h4>heading</h4>
  <p>para1</p>
  <p>para2</p>
</div>

希望对你有帮助!

【讨论】:

  • 对不起,但这在我的情况下不起作用 - 检查像这样的页面 bbc.com/news/uk-england-london-42623651 (理想情况下,代码应该适用于任何新闻网站) - 此页面包含多篇文章介绍和一篇主要文章 -我正在寻找的是只返回主要文章容器的代码 - 这有意义吗?
  • 只需打开任何新闻网站,例如 bbc/cnn/whatever - 然后打开任何文章并将其粘贴到控制台 let story = document.querySelector('* p+p').parentElement; while(!story.querySelector('h1')){ story = story.parentElement; } console.log(story);
  • 他要求一个普通的 javascript 解决方案,而不是 jquery,除非你将它转换为纯 javascript。
【解决方案2】:

我的问题是是否可以将这两个示例合并到一个查询中?

tl;dr:不,不是。当然不是今天,也可能不会很快。如果您对实际答案以外的任何内容都不感兴趣,那么您只需要知道这些;本段之后的所有内容都是与标准中尚不存在的功能有关的背景信息。


这取决于您所说的“单个查询”是什么意思。你的意思是“一个单一的任务”?如果是这样,:has() 伪类 from jQuery,计划用于标准化 in Selectors 4,将大有帮助:

// In jQuery: $('p+p').closest(':has(h1)')
let story = document.querySelector('p+p').closest(':has(h1)');

但请注意,它与Element#closest() 结合使用,此外,:has() 尚不原生支持,并且近期没有计划在任何浏览器中实现它。因此,如果 jQuery 不是一个选项,那么您所拥有的就是您长期以来所拥有的最好的。

如果“单个查询”是指“单个选择器”,那么答案是否定的,因为不可能编写匹配两个或多个后代的最近共同祖先的选择器。最接近的是:has(h1):has(p+p),但这将匹配每个这样的祖先,从最里面的这些祖先开始,一直到根元素。没有选择器只匹配其中最里面的部分。

【讨论】:

    【解决方案3】:

    根据您提供的网站,只需使用子选择器和兄弟选择器。以下将起作用。:

    window.document.querySelector("*>h1, * p+p").parentNode
    

    它选择所有带有 h1 的元素和所有带有多个 p 标签的元素。我在您提供的页面上进行了尝试,它产生了与您的 JS 代码相同的结果。

    一些额外的说明,因为你没有指定 jquery 我给你一个 JavaScript 解决方案。目前没有父选择器或查询选择器,所以 parentNode 是最接近的。最后,您的原始解决方案指定了文章(而不是像页面那样的 div)。如果需要,只需将 div 换成文章即可。

    【讨论】:

    • 诀窍是我不知道是否会有 div、文章、部分或其他内容......我希望它适用于任何网站。此外,您的解决方案不包括 h1
    • 基本上,它和我原来的帖子一样:document.body.querySelector('* p+p').parentElement 只使用 div,而不是任何可能的容器
    • 更新版本 window.document.querySelector("* &gt; h1+p+p").parentNode 不起作用 :(
    • 我想我现在明白了。
    • window.document.querySelector("*&gt;h1, * p+p").parentNode 在某些情况下有效,但在某些情况下会失败,例如这里 tsn.ua/svit/…
    猜你喜欢
    • 2012-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多