template.content.cloneNode(true)是唯一合法取值方式,因template.content为只读DocumentFragment且单次消耗,innerHTML恒为空、children为空 NodeList,不加true则丢失嵌套结构,不可缓存复用,需每次重新克隆。

template.content.cloneNode(true) 是唯一合法取值方式
直接读 template.innerHTML 永远返回空字符串,template.children 是空 NodeList,template.firstElementChild 是 null。浏览器解析时就把内部 HTML 全部转成只读的 DocumentFragment,挂载在 content 属性上——这是唯一能访问它的地方。
克隆必须带 true 参数:template.content.cloneNode(true)。不加 true 只克隆顶层节点,嵌套结构(比如 <div><p><span></span></p></div>)会丢失子元素。
- 不能缓存
template.content复用:它是单次可用的 DocumentFragment,直接appendChild(template.content)后,再调用就“搬家”了,第二次插入会失败 - 每次都要重新调用
.cloneNode(true),哪怕内容没变 - 批量插入多个实例时,先克隆到一个
DocumentFragment,再一次性append到目标容器,避免反复触发重排
填值必须手动操作,不支持自动绑定
template 里写 <input value="default"> 或 <select><option selected>A</option></select>,克隆后显示的是初始 HTML 值,不是用户当前输入或运行时状态。它不跟踪、不响应、不更新。
- 表单控件要显式初始化:
clone.querySelector('input').value = ''或clone.querySelector('textarea').textContent = '' - 优先用
textContent和value填值,不用innerHTML,防 XSS - 如果模板含占位符如
{{title}},得自己写替换逻辑,浏览器原生不解析
事件和资源完全“冻结”,克隆后需重建
template 内的 <script> 不执行,<img src="x.jpg"> 不发请求,<video autoplay> 不播放,onclick="alert(1)" 属性无效,addEventListener 更不会自动绑定——因为节点根本没进 DOM。
立即学习“前端免费学习笔记(深入)”;
- 克隆后的节点是全新实例,所有事件监听器必须重新绑定
- 推荐用事件委托替代逐个绑定:在父容器监听
click,用event.target.matches('.delete-btn')判断来源 -
<slot>在普通 DOM 中无效,只在自定义元素的 Shadow DOM 里起作用,且需配合attachShadow手动处理
IE 完全不支持,polyfill 风险高
IE 浏览器连 document.createElement('template') 创建的元素都没有 content 属性,template.content 直接是 undefined。
- 官方 polyfill(如 webcomponentsjs)对
cloneNode(true)行为模拟不完整,尤其涉及深层嵌套或表单时容易出错 - 真要兼容 IE,建议构建时预编译成字符串模板,用
innerHTML插入,别依赖运行时templateAPI - 现代项目默认放弃 IE 支持更稳妥;若必须保,应把
template用法隔离在 feature detect 之后



















