template标签内容不渲染是规范行为,因其子节点被移入只读的content属性(DocumentFragment),不解析、不执行、不加载资源、不参与渲染;必须用template.content.cloneNode(true)克隆后插入DOM才生效。

template 标签内容不渲染,是因为浏览器把它当作离线 DOM 仓库,所有子节点被封装进只读的 content 属性(一个 DocumentFragment),既不解析、不执行、不加载资源,也不参与渲染树构建——它根本不在 DOM 中。
为什么直接写template里什么也不显示
这不是 bug,是规范行为:template 元素本身是真实节点,但它的子节点全被移出主 DOM,挂载到 content 上。所以:
-
template.innerHTML永远返回空字符串 -
template.children是空的NodeList -
document.getElementById("x")查不到模板里写的 ID,哪怕它看起来“在 HTML 里” - 里面写了
<script>不执行,<img src="xxx">不发请求,<style>不生效
必须用template.content.cloneNode(true)才能插入真实 DOM
想让它“活过来”,只有一条路径:取 content → 深克隆 → 插入容器。缺一不可。
- ❌
container.appendChild(template):插入的是空标签,没内容 - ❌
container.appendChild(template.content):第一次成功,第二次静默失败(content已被移走) - ❌
template.content.cloneNode()(缺true):只克隆空容器,子节点全丢 - ✅
container.appendChild(template.content.cloneNode(true)):每次都是全新副本,结构、表单值、文本节点全保留
克隆后要手动初始化表单值和事件
克隆出来的节点是普通 DOM,但原始模板里的运行时状态不会自动继承:
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
立即学习“前端免费学习笔记(深入)”;
-
<input value="default">克隆后仍显示default,但用户输入的值不会带过来——得手动设clone.querySelector('input').value = data.inputValue - 内联
onclick不生效,得用clone.querySelector('.btn').addEventListener('click', handler) - ID 会重复,改用
class或动态生成data-id,同时同步更新label[for] -
<slot>在普通 DOM 里完全无效,不解析、不报错、不分发内容
批量渲染必须用DocumentFragment中转
循环里每轮都 appendChild 克隆节点,等于让浏览器反复重排重绘,100 条就明显卡顿。
- 先
const frag = document.createDocumentFragment() - 循环体内:克隆 → 填值 →
frag.appendChild(cloned) - 循环结束,只调一次
container.appendChild(frag)
真正容易被忽略的一点:你不能缓存 template.content 复用,也不能靠 CSS 选中它里面的内容;它连 display: none 都不是——它压根不在 DOM 树里,连样式都不计算。


















