template标签将HTML内容转为离线DocumentFragment,不解析、不渲染、不加载资源、不执行脚本;克隆必须用content.cloneNode(true),且需手动初始化表单值与事件绑定。

template 标签天生就是干这事的:它把 HTML 骨架“冻住”,不解析、不渲染、不加载资源、不执行脚本——只等你用 JS 显式取出来。
为什么直接写在 template 里内容不显示也不执行
浏览器遇到 <template>,会立刻把内部所有内容转成一个离线的 DocumentFragment,挂到 content 属性上。此时:
-
<script>标签被跳过,console.log不触发 -
<img src="xxx">不发请求,onerror不回调 -
<video autoplay>不播放,controls不出现 - 所有
onclick或addEventListener绑定都无效(节点还没进 DOM)
克隆时必须用 content.cloneNode(true),不能用 innerHTML
template.innerHTML 永远返回空字符串;template.children 是空的 NodeList——因为真实子节点全在 content 里,且是只读的 DocumentFragment。
- ✅ 正确:
template.content.cloneNode(true)(深克隆,保留所有嵌套结构) - ❌ 错误:
template.innerHTML、template.children[0]、template.firstElementChild - ⚠️ 注意:
cloneNode(true)复制的是初始 HTML 状态,不是运行时值(比如<input value="a">克隆后仍是value="a",哪怕用户已改成 "b")
含表单或交互元素时,克隆后要手动初始化
模板里的 <input>、<select>、<textarea> 克隆后保留的是定义时的 value 或 checked,不是当前用户输入。常见处理方式:
立即学习“前端免费学习笔记(深入)”;
- 克隆后立即设置
input.value = ''或input.checked = false - 如果需保留初始值(如默认选中),显式赋值:
clone.querySelector('input').value = 'default' - 事件监听器不会随克隆复制,必须重新绑定,或改用事件委托(如监听父容器的
click,再判断event.target.matches('.delete-btn'))
多个克隆实例共用同一份 template,但不能重复 append 同一个 fragment
template.content 是一个 DocumentFragment 实例,只能被插入 DOM 一次。第二次 appendChild() 会静默失败——它自动从原位置移走,再插入新位置,不会复制。
- 每次都要重新调用
cloneNode(true),不能缓存template.content直接复用 - 大量渲染时,建议先批量克隆进
DocumentFragment,再一次性appendChild到目标容器,减少重排重绘 - IE 完全不支持
template,若需兼容,必须加 polyfill(如document.createElement('template')+ 手动补content属性)
真正容易被忽略的一点:template 的“惰性”是彻底的——它连 CSS 都不应用,哪怕内联 <style> 也得等克隆进 DOM 后才生效;而一旦进 DOM,就完全脱离 template 控制,变成普通节点了。



















