浏览器如何处理 <template> 标签与 <div> 标签

How does a browser handle a <template> tag VS a <div> tag

我一直在阅读有关 <template> 标签的文档,我似乎无法理解它与简单地使用 <div>display: none;[= 有何不同20=]

文档:template tag

<template> 示例

<template id="productrow">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template>

VS <div> 例子

<div id="productrow" style="display: none">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</div>
  1. 在低层次上,浏览器如何以不同方式处理这两个示例?
  2. 某些 JS 方法或 HTML 属性是否不同或不可用?

PS:我知道浏览器兼容性差异

考虑:

<template>
  <style>
    body: { background-color: black; }
  </style>
  <script>
    alert('hello');
  </script>
  <audio src="alert.wav" autoplay></audio>
</template>

并且:

<div style="display: none;">
  <style>
    body: { background-color: black; }
  </style>
  <script>
    alert('hello');
  </script>
  <audio src="alert.wav" autoplay></audio>
</div>

当浏览器呈现它们时,它们的行为是否相同? (剧透:没有。)

不过,要解决您的具体问题:

  1. On a low level, how does the browser handle these 2 examples differently?

首先,<template> 中的 HTML 不会成为 <template> 的子元素 DOM。它成为 "inert" DocumentFragment 的子节点(间接地;这是一种简化),它们作为节点存在但不 "do" 任何东西,如上例所示。

除了 "inert," 之外,模板内容没有 "conformance requirements." 您上面的 <tr> 示例很好。看看这里发生了什么:

const template = document.querySelector('template');
const div = document.querySelector('div');

console.log('template.innerHTML is', template.innerHTML);
console.log('div.innerHTML is', div.innerHTML);
<template>
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template>

<div style="display: none">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</div>

在普通文档中,<tr> 不能是 <div> 的子元素,因此浏览器会将其删除。在 <template> 中,该要求不存在。你会发现与 <div style="{{myStyle}}"> 相同。在文档中,浏览器会丢弃 style 属性,因为它的值无效;在 <template> 中它不会。这就是 <template> 对模板有用的原因。

如果您想了解更多关于 <template> 是如何渲染的,我建议您阅读 section about it in the HTML spec。读起来并不容易,部分内容可能难以理解,但你会学到很多东西。

  1. Are certain JS methods or HTML attributes different or not available?

<template> 元素具有 content 属性,指向上面讨论的 DocumentFragment。

JS 中的任何选择器都找不到 <template> 内的元素,因此您不会意外找到它们,要提取它们,您必须使用 content 属性 的 HTMLTemplateElement 使用类似的东西:

var clone = document.importNode(templateElement.content, true);

此外,每个 <style><audio>/<video>/...<script> 都会在页面加载时被解析,但 运行 直到您将其克隆到主 [=21] =].

我找到了一篇详细解释所有差异的文章: https://www.html5rocks.com/en/tutorials/webcomponents/template/

我现在意识到 <div> 示例实际上是旧版浏览器中使用的一种 polyfill,必须进行严重的黑客攻击才能使其按预期工作。

感谢大家的帮助。