template 是已解析的 documentfragment,必须用 clonenode(true) 或 importnode(content, true) 克隆复用;直接 appendchild(content) 仅一次有效;innerhtml 恒为空;克隆后须重置表单值、重绑事件、更新 id。

template 标签不是“隐藏的 div”,也不是“可直接插入的 HTML 字符串”——它是一个已解析但挂起的 DocumentFragment,必须用 cloneNode(true) 才能真正复用。直接 appendChild(template.content) 只能成功一次,第二次静默失败。
为什么 template.innerHTML 总是空字符串
因为浏览器把内容全塞进了只读的 content 属性(类型为 DocumentFragment),而不是作为子节点挂在元素上。所以:
-
template.children返回空NodeList -
template.firstElementChild是null -
template.innerHTML永远返回""
别试了,这条路不通。唯一合法入口是 template.content,然后必须立刻 cloneNode(true)。
template.content.cloneNode(true) 必须加 true
不加 true 就等于白克隆:只复制一个空的 DocumentFragment 容器,所有子节点全丢。常见错误是写成 cloneNode(false) 或漏掉参数,结果插入后页面啥也没有。
-
cloneNode(true):深克隆,带全部子节点和文本,可用 -
cloneNode(false):只克隆 fragment 本身,没内容,基本废了 -
document.importNode(template.content, true)效果等价,语义更清晰,推荐在需要强调“导入”语义时用
克隆后必须手动初始化表单、事件和 ID
模板里的 <input value="a"> 克隆出来还是 value="a",但不会反映用户当前输入;onclick 属性无效;id 重复会导致 document.getElementById 返回错对象。
- 表单控件要重置:
clone.querySelector('input').value = ''或设为实际值 - 事件必须重新绑定:
clone.querySelector('button').addEventListener('click', handler) - ID 必须清除或重生成:
clone.querySelector('[id]').id = 'new-id-' + Date.now() - 避免内联样式和
<style></style>:它们在template里不生效,插入后可能全局污染
批量插入时别反复 appendChild,用 DocumentFragment 中转
循环里每次 appendChild 都会触发重排,性能差。尤其渲染几十个卡片时,卡顿明显。
- 先创建临时 fragment:
const frag = document.createDocumentFragment() - 循环克隆并修改,然后
frag.appendChild(clone) - 最后一次性
container.appendChild(frag) - IE 不支持
template,连document.createElement('template').content都是undefined,现代项目直接放弃,别硬扛
最常被忽略的不是语法,而是克隆后对 id 的处理——它不报错,但会让 CSS 选择器和 getElementById 行为不可靠,问题延迟暴露,调试成本翻倍。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











