<template> 是一个惰性 DOM 片段容器,内容仅在 cloneNode 后插入才生效;其 content 为只读 DocumentFragment,需克隆后修改并插入,且须手动处理 ID 等唯一属性以避免重复。
<template> 是一个不渲染、不执行、不加载资源的原生 HTML 容器,它的内容只在你用 JavaScript 显式克隆并插入 DOM 时才“活过来”。
它不是占位符,也不是隐藏元素(比如 display: none 的 <div>),而是一个语法合法但完全惰性的 DOM 片段容器。
<template> 的 content 属性返回 DocumentFragment,必须 cloneNode 才能复用<template> 内部的 HTML 会被浏览器解析,但不会构建真实 DOM 节点,也不会触发脚本执行、图片加载、音频播放等副作用 content 属性是一个 DocumentFragment,不能直接 append 到页面——必须先调用 cloneNode(true) innerHTML 会得到空字符串;直接访问子节点(如 firstChild)会是 null 常见错误写法:
document.body.appendChild(template.content) → 报错或静默失败 template.innerHTML = "..." → 无效,innerHTML 是只读的 正确做法:
立即学习“前端免费学习笔记(深入)”;
const clone = template.content.cloneNode(true) const clone = template.content.cloneNode(true);clone.querySelector('h3').textContent = '新标题';document.body.appendChild(clone);
<tr><div><td>xxx</td></div></tr> 会被解析器强行“修复”成非法结构(比如把 <div> 提到表格外) <template> 里,这段代码会原样保留在 content 中,DOM 结构完全可控 注意点:
</p>),<template> 不会帮你补 content 可能为空)id="submit-btn" 或 for="email",会导致 DOM ID 重复 document.getElementById)行为不可靠 const clone = template.content.cloneNode(true);clone.querySelector('[id]').id = 'submit-btn-' + Date.now();clone.querySelector('[for]').setAttribute('for', 'email-' + Date.now());
也可以用 dataset 或 class 替代 ID 来做逻辑绑定,更安全。
<template> 看似简单,但真正用好它,关键是理解它和普通 DOM 的“隔离边界”:它不参与初始渲染流水线,也不享受运行时容错,所有结构、属性、绑定都得你亲手操刀。漏掉一次 cloneNode,或忘了清理 ID,就可能卡在 DOM 查询失败或样式错乱上。