template标签是离线容器,不渲染不执行;必须用template.content.cloneNode(true)获取内容,填值优先用textContent/value而非innerHTML以防XSS和事件丢失;批量插入须用DocumentFragment避免重排重绘。

template 标签本身不渲染、不执行、不绑定,它只是个离线容器。想靠它实现“高效渲染流”,必须手动克隆 + 填值 + 批量插入,没有自动更新或响应式逻辑。
为什么 template.content.cloneNode(true) 是唯一入口
很多人卡在第一步:用 document.querySelector('template').innerHTML 拿不到内容,返回空字符串。这是因为 template 的真实子节点被包裹在 DocumentFragment 里,只能通过 content 属性访问。
-
template.innerHTML永远为空,别用 -
template.textContent返回所有文本(含换行缩进),但无法操作 DOM 结构 - 不加
true是浅克隆:子元素事件监听器、input光标位置、表单状态全丢
填值时别碰 innerHTML,优先用 textContent 和 value
用 innerHTML 拼接字符串填值,等于主动引入 XSS 风险,还会意外销毁已绑定的事件监听器(比如模板里原本有 button,克隆后 onclick 就没了)。
- 纯文本内容:
el.querySelector('.title').textContent = data.title - 表单控件:
el.querySelector('input').value = data.value,不是textContent - 需要保留 HTML 结构?先对用户输入做转义(如
text.replace(/&/g, '&')),再塞进innerHTML - 模板中含
<script></script>或<style></style>?cloneNode(true)不会执行脚本,也不会重复加载样式
批量插入必须用 DocumentFragment,否则性能崩得快
循环里每轮都 container.appendChild(cloned),等于让浏览器反复重排重绘。100 条数据可能就明显卡顿;500 条基本卡死。
立即学习“前端免费学习笔记(深入)”;
- 先
const frag = document.createDocumentFragment() - 循环体内:克隆 → 填值 →
frag.appendChild(cloned) - 循环结束后,只调一次
container.appendChild(frag) -
frag是轻量中间容器,不能被querySelector查到,也不在 DOM 树中
data- 属性能留,slot 不生效,别混用 Web Components 逻辑
想存 ID 或索引?data-id 可以保留在克隆节点上,但不会自动变成 JS 对象属性;想用 slot 分发内容?原生 template 不激活 slot 机制——它没挂载到 Shadow DOM,slot="xxx" 根本不解析。
错误示范:<template><slot name="title"></slot></template> + cloned.querySelector('[slot="title"]').textContent = 'xxx',实际无效,因为没定义 shadowRoot,slot 根本没激活。



















