是唯一原生、零依赖、惰性解析的客户端模板方案,其内容不渲染、不执行脚本、不加载资源;和存在解析缺陷、性能浪费与可访问性问题;应使用document.importnode(template.content, true)安全克隆并结构化绑定数据。

<template></template> 标签是唯一原生、零依赖、不执行脚本也不触发资源加载的客户端模板方案。它不是“占位符”,也不是“注释容器”,而是一个明确语义的惰性 DOM 片段容器——浏览器会解析其内容,但跳过渲染、样式应用、脚本执行和图片加载。
为什么不能用 <script type="text/html"></script> 或 <div hidden> 替代
<p>这两种写法看起来能“藏住”内容,但存在实质缺陷:<br>• <code><script type="text/html"></script> 中的 HTML 不会被 HTML 解析器处理,嵌套标签、属性引号、实体编码容易出错,innerHTML = template.innerHTML 可能因未转义而 XSS;
• <div hidden> 仍会构建 DOM、计算样式、触发图片加载(即使不可见),且可能被屏幕阅读器误读;<br>• <code><template></template> 的 content 是 DocumentFragment,天然支持深度克隆,节点可直接 append,无需字符串拼接或 innerHTML 解析。
document.importNode(template.content, true) 是标准克隆方式
document.importNode(template.content, true) 是标准克隆方式别直接用 template.content.cloneNode(true)——它在部分旧版 Safari 中返回空 fragment;importNode 是跨浏览器安全的克隆入口:
• 必须传 true(深克隆),否则只复制顶层 DocumentFragment,内部节点丢失;
• 克隆后的内容脱离原 <template></template> 上下文,可自由修改、绑定事件、插入任意位置;
• 示例:
const tmpl = document.querySelector('#item-tmpl');<br>const frag = document.importNode(tmpl.content, true);<br>frag.querySelector('.title').textContent = '新标题';<br>listEl.appendChild(frag);
动态填充时避开 innerHTML,优先操作 textContent 和 dataset
模板中尽量避免用 {{title}} 这类字符串占位符,改用结构化绑定:
• 给目标元素加 data-bind="title"、data-bind="avatar" 等属性;
• 克隆后遍历 frag.querySelectorAll('[data-bind]'),按 key 映射数据,写入 textContent(防 XSS)或 dataset;
• 图片地址用 img.setAttribute('src', url),而非拼进 innerHTML;
• 不要对整个 fragment 做 innerHTML = ...,那等于放弃 <template></template> 的安全性优势。
<style></style> 和 <script></script> 完全静默——它们不会生效,也不会报错。如果你依赖模板内联样式或初始化逻辑,必须在克隆后手动注入或调用,而不是指望它“自动运行”。










