什么是jQuery的.is(':empty')的DOM / Vanilla Javascript等效项

时间:2019-03-20 16:09:21

标签: javascript jquery

我想编写一段代码,以遍历页面的document.body并报告所有空块级DOM节点。这是SEO / a11y的通行证。

我发现这篇文章似乎会有所帮助:

https://css-tricks.com/snippets/jquery/check-for-empty-elements/

$('*').each(function() {
         if ($(this).is(':empty') == "") {
                   //Do Something
         }
});

问题#1:如何将.is(':empty')转换为普通js:

function isEmpty(el) {
  // Robust isEmpty logic here
}
document.querySelectorAll('*').filter(el => {
  return isEmpty(el);
});

问题2:这个逻辑是否也会遍历所有孩子?

问题3:我们可以仅对块级元素使用此querySelector吗?

2 个答案:

答案 0 :(得分:9)

“ {empty”(空)的DOM版本是没有子节点,您可以通过多种方式检查子节点,最常见的两种可能是:

    如果没有子节点,
  • firstChild将为null
  • 如果没有子节点,则childNodes中的length将是0

例如,由于null是虚假的,而filter使用的是真实/虚假值:

const allEmpty = [...document.querySelectorAll('*')].filter(el => !el.firstChild);

(请注意,querySelectorAll返回一个NodeList,而NodeList没有一个filter方法,因此我在此处使用了扩展符号从{{ 1}} [因为NodeList iterable 的规范;但是请参阅this answer关于确保NodeList iterable 的信息在您的环境中]。

  

问题2:这个逻辑是否也会遍历所有孩子?

NodeList在文档中选择每个元素,其中许多元素也会在列表中的其他元素之内。

  

问题3:我们可以仅对块级元素使用此querySelector吗?

您当然可以根据当前规范对其进行定制,并且默认的querySelectorAll('*')浏览器可以通过列出诸如display之类的标记列表来对其应用。但这并不能告诉您什么是该页面上的块元素,因为CSS可以更改元素的querySelectorAll("div, p, h1"/*...*/)。要获取最新信息,您需要在选择每个元素后使用getComputedStyle并检查结果display

在页面上所有的元素列表可能并不理想,您可以考虑使用递归函数:

display

但这部分归结为您认为“空”的部分。 jQuery的function findEmpty(element, results = []) { let child = element.firstChild; if (!child) { results.push(element); } while (child) { if (child.nodeType === Node.ELEMENT_NODE) { findEmpty(child, results); } child = child.nextSibling; } return results; } const allEmpty = findEmpty(document.body); 选择器是完全文字的:元素只有在没有任何子节点时才为空。但是您的定义可能更松散-例如,也许您出于您的目的考虑只包含空格(直接或在子元素中)为空的元素(在这种情况下为:empty)。上面的第一个链接是有关MDN的DOM信息,如果需要,您可以进行很多研究以确定自己的“空”。

答案 1 :(得分:0)

您可以使用children,它不同于childNodes,后者可以包含任何节点,包括文本节点。如果在childNodes.length上使用div之类的<div>Some Text here</div>,即使没有子元素或html标记,也会返回一个非空数组

function isEmpty(el) {
  return el.children.length
}
[...document.querySelectorAll('div.parent')].filter(function(el) {
  let k = isEmpty(el);
  console.log(k)
});
<div class='parent'>
  <div>Child 1</div>
  <div>Child 1</div>
  <div>Child 1</div>
  <div>Child 1</div>
</div>

<div class='parent'></div>