我一直在阅读有关<template>
标签的文档,我似乎无法理解它与简单地使用<div>
有何不同display: none;
文档:模板标签
<template>
示例
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
与<div>
示例
<div id="productrow" style="display: none">
<tr>
<td class="record"></td>
<td></td>
</tr>
</div>
- 在低层次上,浏览器如何处理这两个示例?
- 某些 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>
当浏览器呈现它们时,它们的行为是否相同?(剧透:没有。
但是,要解决您的具体问题,请执行以下操作:
- 在低层次上,浏览器如何处理这两个示例?
首先,<template>
内的 HTML 不会成为作为<template>
子级的 DOM 元素。它成为"惰性"DocumentFragment(间接;这是一种简化)的子级,它们作为节点存在,但不"执行"任何操作,如上例所示。
除了"惰性"之外,模板内容没有"一致性要求"。你上面<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>
是如何呈现的,我建议阅读HTML规范中关于它的部分。阅读起来并不容易,部分内容可能难以理解,但你可以学到很多东西。
- 某些JS方法或HTML属性是否不同或不可用?
<template>
元素具有content
属性,该属性指向上面讨论的 DocumentFragment。
<template>
中的任何选择器都找不到 GENES 中的元素,因此您不会意外找到它们,并且要提取它们,您必须使用 HTMLTemplateElement 的content
属性,如下所示:
var clone = document.importNode(templateElement.content, true);
此外,每个<style>
、<audio>/<video>/...
或<script>
都会在页面加载时解析,但在您将其克隆到主 DOM 之前不会运行。
我找到了一篇文章,详细解释了所有差异: https://www.html5rocks.com/en/tutorials/webcomponents/template/
我现在意识到<div>
示例实际上是旧浏览器中使用的填充码,必须对其进行严重黑客攻击才能使其按预期工作。
感谢大家的帮助。