template 标签是离线 HTML 仓库,不渲染、不执行、不绑定;其内容在 template.content 中,需 cloneNode(true) 克隆并手动填充数据,避免 innerHTML XSS 风险与事件丢失,批量插入须用 DocumentFragment 提升性能。

template 标签本身不渲染、不执行、不绑定,它只是个离线的 HTML 仓库。想用它做列表或动态插入,必须靠 JS 手动克隆、填值、插入——没有自动循环,也没有响应式更新。
为什么 template.innerHTML 总是空?
因为 template 的内容被封装在 content 文档片段里,不是普通子节点。直接读 innerHTML 或 textContent 拿不到结构,浏览器会返回空字符串。
- 正确入口永远是
template.content,它是只读的DocumentFragment -
template.content.cloneNode(true)是唯一安全克隆方式;用innerHTML拼接再塞进template,克隆后不会生效 - 如果模板里有
<script>或<style>,cloneNode(true)不会执行脚本,也不会重复注入样式
如何正确填充数据:别用 innerHTML,优先选 textContent 和 value
填值时若直接改 innerHTML,容易引入 XSS 风险,还会意外销毁已绑定的事件监听器(比如按钮上的 onclick)。
- 文本内容一律用
el.textContent = data.name - 表单控件用
input.value = data.price,而不是innerHTML - 需要保留 HTML 结构?先确认是否真有必要;若必须,对用户输入做严格转义,或改用
DOMParser解析 - 用
querySelector定位目标元素,别依赖顺序或索引——模板结构一变就崩
批量插入必须用 DocumentFragment,否则性能崩得快
循环里对真实 DOM 反复 appendChild,每轮都触发重排重绘。100 条数据可能卡顿明显,200 条基本可感知延迟。
立即学习“前端免费学习笔记(深入)”;
- 先
const frag = document.createDocumentFragment() - 每次克隆后,填完值就
frag.appendChild(cloned) - 循环结束,只调一次
container.appendChild(frag) -
frag是轻量中间容器,不能被querySelector查到,也不在主 DOM 树中
data- 属性能留,slot 不生效
克隆后的节点会完整保留 data-id、data-type 这类属性,但别指望它自动映射成 JS 对象字段;更关键的是:slot 在普通 template 中完全不激活。
-
<template><slot name="title"></slot></template>克隆后,cloned.querySelector('[slot="title"]')能拿到元素,但改它的textContent不会“投射”到任何地方——因为没定义shadowRoot,slot机制压根没启动 - 想实现类似功能,得自己用
querySelector找占位节点,再手动填值,别幻想 slot 自动分发 - 如果模板含多个同名
data-属性,记得在 JS 里统一处理逻辑,别靠 CSS 选择器硬匹配
最常被忽略的一点:每次循环都必须调用 cloneNode(true)。复用同一个克隆节点插入多次,所有实例实际指向同一份 DOM 引用,改一个,全跟着变。



















