简体   繁体   English

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

[英]What is the DOM/Vanilla Javascript equivalent of jquery's .is(':empty')

I want to write a snippet of code that will traverse the document.body of a page and report all empty block level DOM nodes. 我想编写一段代码,将遍历页面的document.body并报告所有空块级DOM节点。 This is a pass for SEO/a11y. 这是SEO / a11y的通行证。

I found this article that will seemingly help: 我发现这篇文章似乎会有所帮助:

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

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

Question #1: How would I convert .is(':empty') to vanilla js: 问题1:如何将.is(':empty')转换为普通js:

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

Question #2: Will this logic traverse all children too? 问题2:这个逻辑是否也会遍历所有孩子?

Question #3: Could we make this querySelector for only blocklevel elements? 问题3:能否仅对块级元素使用此querySelector?

The DOM version of "empty" is that there are no child nodes, which you can check in various ways, probably the two most common are: DOM版本中的“空”是没有子节点,您可以通过多种方式进行检查,最常见的两种可能是:

  • firstChild will be null if there are no child nodes 如果没有子节点,则firstChild将为null
  • The length of childNodes will be 0 if there are no child nodes 如果没有子节点,则childNodeslength将为0

So for instance, since null is falsy and filter works with truthy/falsy values: 举例来说,由于null为falsy且filter与true / falsy值一起使用:

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

(Note that querySelectorAll returns a NodeList and NodeList doesn't have a filter method, so I used spread notation there to create an array from the NodeList [since NodeList s are iterable according to the spec now; but see this answer about ensuring that NodeList is iterable in your environment].) (请注意, querySelectorAll返回一个NodeListNodeList没有filter方法,因此我在那里使用了扩展符号从NodeList创建一个数组[因为NodeList现在可以根据规范进行迭代 ;但是请参见有关确保NodeList 此答案。在您的环境中是可迭代的 ]。

Question #2: Will this logic traverse all children too? 问题2:这个逻辑是否也会遍历所有孩子?

querySelectorAll('*') selects every element in the document, many of which will be inside others also on the list. querySelectorAll('*')选择文档中的每个元素,其中许多元素也会在列表中的其他元素之内。

Question #3: Could we make this querySelector for only blocklevel elements? 问题3:能否仅对块级元素使用此querySelector?

You can certainly tailor it according to the current specification and the default display browsers apply to them by doing a list of tag, such as querySelectorAll("div, p, h1"/*...*/) . 您当然可以根据当前规范来定制它,并且默认的display浏览器可以通过做一个标记列表来应用于它们,例如querySelectorAll("div, p, h1"/*...*/) But that doesn't tell you what's a block element on that page , since CSS can change the display of elements. 但这并不能告诉您该页面上的block元素是什么,因为CSS可以更改元素的display To get up-to-date information, you'd need to use getComputedStyle on each element after selecting it and check the display of the result. 要获取最新信息,在选择每个元素并检查结果display后,您需要在每个元素上使用getComputedStyle

Building a list of all of the elements on a page may not be ideal, you might consider a recursive function instead: 在页面上构建所有元素的列表可能并不理想,您可以考虑使用递归函数:

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

But this partially comes down to what you consider "empty." 但这部分归结为您认为“空”的部分。 jQuery's :empty selector is quite literal: An element is only empty if it doesn't have any child nodes. jQuery的:empty选择器非常文字:一个元素只有在没有任何子节点时才为空。 But your definition may be more loose — for instance, perhaps you want to consider an element that contains only whitespace (directly or in descendant elements) "empty" for your purposes (in which case: !el.textContent.trim() ). 但是您的定义可能更松散-例如,也许您出于您的目的考虑只包含空格(直接或在后代元素中)为“空”的元素(在这种情况下: !el.textContent.trim() )。 The first link above is to the DOM information on MDN which gives you lots to explore to determine your own "empty" if necessary. 上面的第一个链接是有关MDN的DOM信息,如果需要的话,它使您可以进行很多探索以确定自己的“空”。

You can use children which is different from childNodes which can contain any node including text node. 您可以使用children是从不同childNodes它可以包含包括文本节点的任何节点。 If using childNodes.length on div like <div>Some Text here</div> will be return a non empty array even though there is no child element or html tags 如果使用childNodes.lengthdiv<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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM