能显著减少静态内容重复渲染开销,因其内容是预解析的 documentfragment,clonenode(true) 仅拷贝节点树、跳过 html 解析;错误写法如 innerhtml += 会触发重排且丢失事件监听器,正确路径是克隆 template.content 后填充插入。

直接用 <template></template> 能显著减少静态内容的重复渲染开销,但前提是它得被正确克隆、填充和插入——不是写个标签就自动生效。
为什么 cloneNode(true) 比 innerHTML += 更快
每次用 innerHTML 拼接字符串,浏览器都要重新解析 HTML、构建 DOM、触发样式计算和布局;而 <template></template> 的 content 是已解析好的 DocumentFragment,cloneNode(true) 只是浅拷贝节点树,跳过解析阶段。
- 错误写法:
container.innerHTML += template.innerHTML—— 触发多次重排,且无法保留事件监听器 - 正确路径:先取
template.content,再用document.importNode(content, true)或content.cloneNode(true) -
cloneNode(true)复制的是结构+属性+文本,但不执行脚本、不加载图片,安全可控 - 若模板含
data-id或class,克隆后全部保留,可直接用于后续查询或绑定
静态内容必须提前定义在 template 中,不能 runtime 生成
<template></template> 的价值在于“预编译”:浏览器在首次加载时就完成结构解析,后续只做克隆。如果 JS 动态拼出 HTML 字符串再塞进 template.innerHTML,等于白用——解析开销又回来了。
- 服务端返回的 HTML 片段(如 fetch 到的 nav.html),必须先注入临时
<template></template>元素,再取其content,否则innerHTML = responseText会触发二次解析 - 不要在
<template></template>里写<script></script>或<style></style>:它们被忽略,逻辑必须由 JS 单独绑定 - 避免在模板中混入响应式占位符(如
{{title}}):原生<template></template>不解析插值,填值必须手动querySelector+textContent
批量插入必须用 DocumentFragment 避免重排
循环里对容器反复 appendChild 每次都触发一次重排,100 条列表可能卡顿明显。真正省性能的关键在“攒一批再上”。
- 创建
const frag = document.createDocumentFragment() - 循环体内:克隆节点 → 填充数据 →
frag.appendChild(cloned) - 循环结束后:单次
container.appendChild(frag) -
frag不在主 DOM 树中,querySelector查不到它,但插入后所有节点立即生效 - 别用
Array.from(template.content.children)直接遍历:content是DocumentFragment,children返回空集合,要用childNodes或先克隆再查
最容易被忽略的是 hydration 边界:如果页面已 SSR 输出了部分结构,又用 <template></template> 动态补内容,ID、data- 属性、甚至 class 名冲突会导致事件绑定失败或样式错乱,得靠命名约定或 runtime 校验来兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











