是惰性 dom 片段仓库,内容解析但不渲染、不执行脚本;必须置于 或 内,通过 template.content 获取 documentfragment,每次插入需 clonenode(true),克隆后需重设 id/for 并手动赋值表单。

template 标签不是“藏 HTML 字符串”的容器,而是浏览器原生的惰性 DOM 片段仓库——内容被解析、结构保留,但不渲染、不执行脚本、不加载图片。真正复用它,关键不在怎么写,而在怎么取、怎么克隆、怎么注入。
模板必须放在合法位置
template 只能直接位于 或 内。嵌套在 <table>、<code><ul></ul>、<div>、<code><script></script> 等元素里,浏览器会静默移除或错位解析,导致 content 为空。
- ✅ 正确:
<template id="card">...</template> - ❌ 错误:
<div><template>...</template></div>(Safari 15.4 前可能丢内容) - ⚠️ 注意:内部可写语义非法结构(如
<p></p> <div>xxx</div>),不影响解析
只能通过 content 获取真实内容
template.innerHTML 永远是空字符串,children 永远为空 NodeList。它的内容被封装在只读的 DocumentFragment 中,唯一合法入口是 template.content。
- ✅ 正确:
const frag = document.querySelector('#card').content; - ❌ 错误:
template.innerHTML.replace(...)、template.firstElementChild、Array.from(template.childNodes) - ⚠️ 关键点:frag 是“移动语义”——首次 appendChild(frag) 后,frag 就空了,再 append 无效
每次插入都必须深克隆
必须用 cloneNode(true),不能省略 true,否则只复制空 fragment 容器,没子节点。
- ✅ 推荐:
const instance = template.content.cloneNode(true); - ❌ 避免:
document.importNode(template.content, true)(Safari 15.4 前对 fieldset/required 表单有校验 bug) - ⚠️ 克隆后节点干净独立,但无事件监听器、无表单状态,需后续手动绑定或赋值
表单与 ID 冲突必须处理
多个实例共用同一模板时,若不重设 id、name、for,label 点击无效、提交字段覆盖、checkValidity() 异常。
- 用
crypto.randomUUID().slice(0, 8)生成唯一 ID,别用 Math.random() - 同步更新
label[for]和对应input[id] - 文本内容优先用
el.textContent = value(防 XSS),属性用el.setAttribute('src', url)(确保资源加载) - 表单控件初始值不能靠 HTML 的
value="xxx",得显式赋el.value = userData.phone











