标签是真正的离线模板容器,其内容不会被解析、不加载资源、不执行脚本、不出现在dom中;必须通过content属性配合importnode或clonenode(true)提取使用。

template 标签不渲染、不执行,是真正的“离线”模板容器
它最大的价值不是语法多酷,而是浏览器明确承诺:<template></template> 里的内容**不会被解析、不会加载资源、不会运行脚本、也不会出现在 DOM 中**,直到你手动把它取出来。这和 <script type="text/template"></script> 或隐藏的 <div style="display:none"> 有本质区别——后者仍会触发图片加载、脚本执行或样式计算。
<p>常见错误现象:用 <code>display: none 包裹模板片段,结果发现页面加载时发出了不该有的图片请求,或者控制台报了未定义变量错误(因为 script 被执行了)。
-
<template></template>内部的<img src="xxx" alt="HTML5的template标签价值在哪_HTML片段复用难吗【阐述】" >不会发起 HTTP 请求 -
<template></template>内部的<script>console.log('hi')</script>完全静默 -
<template></template>的内容在document.body.innerHTML里不可见,也不在document.querySelectorAll('*')结果中
克隆 template 内容必须用 content + importNode 或 cloneNode(true)
直接操作 <template></template> 元素本身没用,它的内容藏在 .content 属性里,这是一个 DocumentFragment。想复用,得先取出来,再插入到真实 DOM —— 而且不能用 innerHTML 搞字符串拼接,否则会丢失事件绑定、表单状态、自定义元素生命周期。
正确做法只有两种:
立即学习“前端免费学习笔记(深入)”;
- 用
document.importNode(template.content, true)(推荐,语义清晰,兼容性好) - 用
template.content.cloneNode(true)(注意:必须传true,否则只克隆空 fragment)
容易踩的坑:template.content.firstChild 可能是文本节点(换行/空格),别直接 append;template.innerHTML 是只读的,改了也没用。
const tmpl = document.querySelector('#item-template');
const instance = document.importNode(tmpl.content, true);
instance.querySelector('span.name').textContent = '张三';
document.getElementById('list').appendChild(instance);
template + innerHTML 混用等于放弃 template 的优势
有人图省事,在 <template></template> 里写 HTML,再用 innerHTML 提取字符串、拼接、再设回 innerHTML —— 这样做完全绕过了 DocumentFragment 的好处,还可能引入 XSS 风险(如果插的是用户数据)。
真正发挥价值的场景是:结构固定、需多次实例化、含表单/媒体/自定义元素。
- 列表项模板(如评论、商品卡片)
- 模态框骨架(含
<input>、<video></video>、<canvas></canvas>) - Web Component 的 shadow DOM 初始化内容
性能影响:用 importNode 克隆比字符串拼接快,尤其在大量重复节点时;但若只是渲染一次静态 HTML,template 并不比直接写 DOM 快多少。
服务端渲染或构建时预编译模板时,template 标签基本无用
如果你用 Vue/React/Svelte,或通过 Webpack/Vite 把模板编译成 JS 函数,<template></template> 标签在最终 HTML 里只是占位符,起不到任何运行时作用。它只对「纯前端、无构建、需动态生成同构 HTML 片段」的场景有意义。
兼容性提醒:IE 完全不支持,Edge 13+、Chrome 26+、Firefox 20+ 支持。如果项目要兼容 IE,别指望它。
复杂点在于:它不解决数据绑定,也不处理条件逻辑——这些还得靠 JS 手动填;它只是把「安全地存一段 HTML」这件事标准化了。很多人以为用了 <template></template> 就等于有了模板引擎,其实它连变量插值都不支持。











