HTML新的template标签

HTML’s New Template Tag
WhatWG HTML 模板规范

WhatWG HTML 模板规范定义了一个新的 <template> 元素,用于描述一个标准的以 DOM 为基础的方案来实现客户端模板。该模板允许你定义一段可以被转为 HTML 的标记,在页面加载时不生效,但可以在后续进行动态实例化。

本文主要摘抄自第一个参考文档

浏览器兼容

<template> 元素的浏览器兼容性如下图:

template标签浏览器兼容

要检查浏览器是否支持 <template> 元素,可以创建该DOM元素并检查它是否拥有 content 属性:

1
2
3
4
5
6
7
8
9
10
11
12
function supportsTemplate() {
return 'content' in document.createElement('template');
}
let sp = document.querySelector('#support_p');
if (supportsTemplate()) {
sp.textContent = '当前浏览器支持 <template> 标签';
sp.style.color = 'green';
} else {
sp.textContent = '当前浏览器不支持 <template> 标签';
sp.style.color = 'red';
}

模版声明

HTML <template> 元素代表标记中的一个模板,它包含”模板内容”;本质上是一大块的惰性可复制 DOM。 可以把模板想象成一个脚手架的零件,在应用的整个生命周期中你都可以使用(和重用)它。

The template element is used to declare fragments of HTML that can be cloned and inserted in the document by script.

要创建模板的内容,需要声明一些标记并用 <template> 元素将它们包裹起来:

1
2
3
4
<template id="mytemplate">
<img src="" alt="great image">
<div class="comment"></div>
</template>

细心的读者可能会注意到那个空图片,这是故意留空的。因为页面加载时不会请求图片,因此就不会产生 404 或控制台错误。我们可以随后动态生成图片的 URL。

模版的特点

<template> 来包裹内容为我们提供了几个重要属性:

  • 它的内容在激活之前一直处于惰性状态。本质上,这些标记就是隐藏的 DOM,它们不会被渲染。
  • 处于模板中的内容不会有副作用。脚本不会运行,图片不会加载,音频不会播放,…直到模板被使用。
  • 内容不在文档中。在主页面使用 getElementById() 或 querySelector() 不会返回模板的子节点。
  • 模板能够被放置在任何位置,包括 <head><body><frameset>,并且任何能够出现在以上元素中的内容都可以放到模板中。 注意,”任何位置”意味着 <template> 能够安全的出现在 HTML 解析器不允许出现的位置…几乎可以作为任何内容模型的子节点。

每一个 <template> 元素都有一个关联的 DocumentFragment 对象(即模版内容)。

激活模版

要使用模板,你得先激活它。否则它的内容将永远无法渲染。 激活模板最简单的方法就是使用 document.importNode() 对模板的 .content 属性进行深拷贝。 .content 为只读属性,关联一个包含模板内容的 DocumentFragment

1
2
3
4
5
let t = document.querySelector('#my-template');
t.content.querySelector('img').src = 'xx/xx/xx.png';
let cloneTmpl = document.importNode(t.content, true);
document.body.appendChild(cloneTmpl);

在对模板进行冲压(stamping out)后,它的内容开始”启用”。 在本例中,内容被拷贝,发出图片请求,最终的标记得以渲染。

示例

模版的惰性

该示例示范了模板内容的惰性。<script> 只有在按钮被按下,模板被激活后才会运行。

1
2
3
4
5
6
7
<button id="useTmpl">使用模版</button>
<div id="container-1"></div>
<template id="tmpl-1">
<div><span>0</span>次使用模版</div>
<script>alert(100);</script>
</template>
1
2
3
4
5
6
document.querySelector('#useTmpl').addEventListener('click', function (e) {
let content = document.querySelector('#tmpl-1').content;
var span = content.querySelector('span');
span.textContent = parseInt(span.textContent) + 1;
document.querySelector('#container-1').appendChild(document.importNode(content, true));
});

从模板中生成 Shadow DOM

很多时候我们会使用 innerHTML 属性为某个元素设置内容,例如在Shadow DOM中;该做法的弊端在于,你的 Shadow DOM 越复杂,就需要越多的字符串拼接操作。这不利于扩展,且该做法最容易滋生 XSS!这时我们就可以使用 <template> 来避免上述问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="container-2"><p>这里是说明</p></div>
<template id="tmpl-2">
<style type="text/css">
:host {
border: 2px dashed green !important;
padding: 4px !important
}
</style>
<div>
<h3>添加评论</h3>
<content select="p"></content>
<textarea></textarea>
<footer><button>发表</button></footer>
</div>
</template>
1
2
let sr = document.querySelector('#container-2').createShadowRoot();
sr.appendChild(document.querySelector('#tmpl-2').content);

这里是说明

文章目录
  1. 1. 浏览器兼容
  2. 2. 模版声明
  3. 3. 模版的特点
  4. 4. 激活模版
  5. 5. 示例
    1. 5.1. 模版的惰性
    2. 5.2. 从模板中生成 Shadow DOM
    3. 5.3. 添加评论
|