template.content.clonenode(true)是唯一可靠克隆方式,因内容存于离线documentfragment中,children为空、innerhtml恒为空字符串,漏掉true仅复制空壳,且需处理id冲突、事件重绑、脚本休眠等问题。

克隆 <template></template> 内容必须走 template.content.cloneNode(true) 这一条路,其他写法要么静默失败,要么只复制空壳。
为什么 cloneNode(true) 是唯一靠谱的克隆方式
浏览器把 <template></template> 的内容存在一个离线的 DocumentFragment 里,它不参与主 DOM 树,也不暴露给常规 DOM 查询方法。
-
template.children永远是空数组 —— 它根本没子节点可枚举 -
template.innerHTML在所有现代浏览器中都返回空字符串,不是 bug,是规范行为 -
template.appendChild(node)会静默失败,因为 fragment 不是合法子节点 - 漏掉
true参数(即写成cloneNode(false))只会复制一个空 fragment,内部结构全丢
克隆后必须处理的 ID 和 name 冲突
直接克隆会原样复制 id、name、for 属性,多个相同 id 会导致 document.getElementById() 只返回第一个,label[for] 失效,表单校验异常(比如 Safari 下 checkValidity() 返回 false)。
- 每次克隆后要重设:
el.id = `item-${counter++}`、el.name = `field-${counter}` - 关联的
label[for]必须同步更新,否则点击 label 不聚焦对应 input - 特别注意
<input type="radio">—— 同名name会让它们互斥,必须确保每组 radio 的name唯一或按需分组
template 里的 script 和 style 默认不生效
<template></template> 是惰性容器,内部 <script></script> 不执行、<style></style> 不注入、图片不加载。克隆后这些节点仍处于“休眠”状态。
- 内联
<script></script>:克隆后需手动提取、创建新<script></script>节点并插入document.head或document.body - 建议逻辑抽离到主 JS 中统一管理,模板里别放
<script></script> -
<style></style>同理,优先用全局 CSS 或<style scoped></style>(注意兼容性) - 含
<slot></slot>的模板克隆后不会自动分发内容 ——<slot></slot>只在自定义元素的 Shadow DOM 中有效
高频渲染时怎么避免重复解析性能损耗
如果一个模板要渲染 50+ 条数据,每次都调用 template.content.cloneNode(true) 会重复解析 HTML 结构,不如缓存一次“干净实例”再克隆它。
- ✅ 正确缓存:
const cached = template.content.cloneNode(true)(缓存的是可插入的 DOM 片段) - ✅ 后续生成:
cached.cloneNode(true)—— 比反复访问template.content快得多 - ❌ 错误缓存:
const cached = template.content—— 这只是只读 fragment,不能直接插入 - 批量插入时务必用
DocumentFragment中转,避免循环中反复触发重排重绘
真正容易被忽略的不是怎么克隆,而是克隆之后——ID 冲突、事件未重绑、<script></script> 沉睡、<slot></slot> 失效,这些都不会报错,但会让功能悄悄失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











