标签本身惰性不阻塞解析,但innerhtml赋值或频繁clonenode会触发重排;应优先用documentfragment离线组装后单次插入,避免布局抖动。

template 标签本身不阻塞解析,但 innerHTML 或 cloneNode 会触发重排
很多人误以为 <template></template> 是“性能黑洞”,其实它天生惰性:浏览器遇到 <template></template> 会跳过解析、不构建 DOM、不加载资源(图片、iframe)、不执行脚本。它只是把内容存为 DocumentFragment,零开销。
真正掉进坑里的,是后续操作方式:
- 用
innerHTML = template.innerHTML赋值 —— 这会强制浏览器反序列化字符串、重新解析 HTML、重建整个子树,哪怕只插入一个按钮,也会重排已存在的全部兄弟节点 - 用
template.content.cloneNode(true)后直接appendChild到已挂载容器 —— 每次调用都可能触发一次重排,100 次就是 100 次布局计算 - 在循环中反复读取
offsetHeight或getComputedStyle再写样式 —— 浏览器被迫同步回流,产生布局抖动(Layout Thrashing)
预编译模板内容要走 DocumentFragment,别拼字符串
如果你在 JS 里动态生成 HTML 片段,比如渲染列表项,<template></template> 的最佳搭档不是字符串拼接,而是离线组装:
- 先
const frag = document.createDocumentFragment() - 循环中创建元素、设属性、append 到
frag(不是真实 DOM) - 最后只调用一次
container.appendChild(frag)
这样浏览器只做一次布局和绘制,比逐个 appendChild 快 5–10 倍。注意:frag 插入后自动清空,不能复用;如需多次插入,每次新建。
template 中的 script 和 link 不执行,但 src/href 仍会预加载
<template></template> 内的 <script src="a.js"></script> 不会执行,<link rel="stylesheet"> 也不会应用,这点安全可靠。但现代浏览器(Chrome/Firefox/Edge)仍会提前发起对 src 和 href 的请求 —— 尤其当模板被 JS 提前读取(如 document.querySelector('template').content)时,资源预加载就已开始。
这意味着:
- 不要在
<template></template>里放你根本不会用到的<img src="big-banner.jpg">,它照样下载 - 若模板用于懒加载场景(如折叠面板展开才用),建议把图片 URL 存为 data 属性,JS 控制时再赋给
src - 第三方字体或分析脚本的
<link>/<script></script>放进<template></template>并不能“隔离”它们,只是延迟执行,不延迟加载
服务端模板(如 Go html/template)和客户端 template 标签不是一回事
这是最容易混淆的点。<template></template> 是纯前端 DOM API,和服务端模板引擎(如 Go 的 html/template、PHP 的 Twig)完全无关。前者在浏览器内存里操作 Fragment,后者在服务端生成最终 HTML 字符串并吐给浏览器。
如果你在优化首屏速度,关键不在 <template></template> 怎么写,而在:
- 服务端是否预编译了模板(避免每次请求都
ParseFiles) - 返回的 HTML 是否内联了 critical CSS,是否 defer 了非首屏 JS
- 是否用了
preload提前拉取模板依赖的字体或数据接口
客户端 <template></template> 只影响“二次渲染”(如 tab 切换、列表增删),它的性能瓶颈永远在 JS 如何操作 DOM,而不是标签本身。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











