template标签内容不进入dom,需通过template.content.clonenode(true)克隆使用;填值优先textcontent,批量渲染用documentfragment;slot和内联事件在template中无效,事件须手动绑定。

template 标签不是“写完就能用”的模板,它压根不进 DOM、不执行脚本、不加载图片——你直接 innerHTML 读它会是空的,querySelector 找不到子元素,CSS 选不到它里面的内容,display: none 都比它“重”得多。想让它变成真实节点,必须靠 JS 主动克隆、填值、插入。
为什么 template.content 是唯一合法入口
template 的内容被浏览器标记为“惰性”,只存于 content 属性中,是个 DocumentFragment。直接 appendChild(template) 或 innerHTML 赋值都无效;template.innerHTML 永远为空字符串;template.firstElementChild 是 null。
- 正确做法:用
template.content.cloneNode(true)获取可复用副本(true表示深克隆) - 错误做法:试图
template.querySelector('img')—— 返回null,因为子节点不在主 DOM 树里 - 注意:
document.importNode(template.content, true)也可用,但cloneNode更轻量、更常用 - 切记:
template.content是“移动式引用”,appendChild(template.content)会清空模板,后续再调用就拿不到内容了
填值时该用 textContent 还是 innerHTML
填文本内容优先用 textContent,填 HTML 片段才考虑 innerHTML;后者有 XSS 风险,且可能破坏结构(比如插错闭合标签导致父容器错位)。
- 安全场景:标题、价格、用户名等纯文本 → 一律用
el.textContent = data.title - 可控场景:后台已过滤的富文本(如 CMS 管理员输入)→ 可用
el.innerHTML = data.desc,但需确保内容不含<script></script>或事件属性 - 禁止操作:把用户输入直接塞进
innerHTML,尤其含onerror=alert(1)类属性 - 表单控件填值统一用
value属性,不用textContent或innerHTML
批量渲染列表必须用 DocumentFragment
循环里反复 container.appendChild(card) 会触发多次重排(reflow),性能断崖式下跌;100 条数据可能卡顿明显。正确方式是先攒到 DocumentFragment,再一次性插入。
- 写法示例:
const fragment = document.createDocumentFragment(); data.forEach(item => { const card = template.content.cloneNode(true); card.querySelector('.product-name').textContent = item.name; card.querySelector('.product-price').textContent = `¥${item.price}`; fragment.appendChild(card); }); container.appendChild(fragment); - 不要用数组 push +
fragment.append(...cards),IE 不支持扩展运算符传NodeList - 若需保留原始模板节点引用(比如后续要动态更新某一项),克隆后记得给每个副本加唯一
data-id - 滚动触发型组件(如“加载更多”商品)务必搭配
IntersectionObserver,避免提前克隆大量节点吃光内存
slot 和内联事件在 template 里完全无效
slot 只在自定义元素的 Shadow DOM 中起作用;onclick="doSomething()" 这类内联事件在 template 中不会绑定,克隆后也不会自动激活——JS 必须手动 addEventListener。
-
template里的<slot></slot>标签会被当成普通标签解析,不具分发能力 - 克隆后的节点,所有事件都得重新绑定:
card.querySelector('.add-to-cart').addEventListener('click', handler) - 如果模板里写了
<style>...</style>,克隆后仍保留在片段中,但样式作用域仅限该片段(无全局污染),不过重复插入会导致多份<style></style>标签 - 模板中
<script></script>不会执行,也不建议放——逻辑应统一收口到外层 JS,便于调试和复用
最容易被忽略的是:克隆后的节点和原始 template 完全解耦,改原始模板不影响已插入的节点;反过来,已插入节点的修改也不会反馈回模板。所谓“可配置”,本质就是每次都要重新克隆+填值+绑定——没有捷径,也没有响应式代理层。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











