为什么 getElementsByTagName 不返回带有标签名称的元素?

Why is getElementsByTagName not returning the elements with the tag name?

我正面临这个我归结为 MWE 的奇怪问题。我不是这方面的专家,抱歉,如果这是显而易见的。

我有这个 HTML 文档:

var floats = document.getElementsByTagName("custom-float");
for (var i = 0; i < floats.length; i++) {
  var caption = floats[i].getElementsByTagName("float-caption");
  if (caption.length == 0) {
    throw 'This float has no caption!';
  }
}
<p>
  A paragraph.
  <custom-float>
    <div style="display: flex;">
      <image src="1.svg"></image>
    </div>
    <float-caption>A description of the image.</float-caption>
  </custom-float>
</p>

出于某种原因,当我打开 HTML(在 Firefox 90.0 和 Linux 中的 Brave 1.26.77 中)时,会抛出 This float has no caption! 错误,所以这意味着 getElementsByTagName 没有返回 float-caption 元素。

令我惊讶的是,我注意到如果我删除 <div style="display: flex;"></div> 包装器 and/or 如果我将 </p> 放在 <custom-float> 之前,一切都会按预期进行。 IE。以下两个 HTML 文档工作正常:

var floats = document.getElementsByTagName("custom-float");
for (var i = 0; i < floats.length; i++) {
  var caption = floats[i].getElementsByTagName("float-caption");
  if (caption.length == 0) {
    throw 'This float has no caption!';
  }
}
<p>
  A paragraph.
  <custom-float>
    <image src="1.svg"></image>
    <float-caption>A description of the image.</float-caption>
  </custom-float>
</p>

var floats = document.getElementsByTagName("custom-float");
for (var i = 0; i < floats.length; i++) {
  var caption = floats[i].getElementsByTagName("float-caption");
  if (caption.length == 0) {
    throw 'This float has no caption!';
  }
}
<p>
  A paragraph.
</p>
<custom-float>
  <div style="display: flex;">
    <image src="1.svg"></image>
  </div>
  <float-caption>A description of the image.</float-caption>
</custom-float>

仅通过标签使用 querySelectorAll 更容易

var floats = document.querySelectorAll("custom-float");
for(var i = 0; i < floats.length; i++) {
    var caption = floats[i].querySelectorAll("float-caption");
    if (caption.length == 0) {
        throw 'This float has no caption!';
    }
}

您的元素正在 DOM 中重新定位,因为给定的 HTML 无效:div elements can't be inside p elements,它只能有 phrasing内容,而不是像 div 这样的 flow 内容。如果您在浏览器中使用 DOM 检查器检查结构,您会看到 div 及其内容已从 p 中移出(因此从 custom-float) 进入 p 的父级。

如果您将 p 替换为 div(或删除 div,如您所见),则不会出现该问题,因为 HTML 不再无效。

此处将 p 替换为 div:

var floats = document.getElementsByTagName("custom-float");
for(var i = 0; i < floats.length; i++) {
    var caption = floats[i].getElementsByTagName("float-caption");
    if (caption.length == 0) {
        throw 'This float has no caption!';
    }
}
<!DOCTYPE html>
<html>
 <head>
    <title>MWE</title>
    <meta charset="utf-8">
 </head>
 
 <body>
    <div>
        A paragraph.
        <custom-float>
            <div style="display: flex;">
                <image src="1.svg"></image>
            </div>
            <float-caption>A description of the image.</float-caption>
        </custom-float>
    </div>
 </body>
</html>