使用<script type="text/x-template">缓存HTML片段最轻量,无需构建工具、不触发网络请求、不执行脚本,适合老项目或微前端子页面;浏览器原生忽略该type,内容仅存于DOM树中,需主动提取innerHTML使用。

用 <script type="text/x-template"> 缓存 HTML 片段最轻量
不需要构建工具、不触发网络请求、不执行脚本,适合老项目或微前端子页面。浏览器原生忽略这种 type,内容只存 DOM 树里,直到你主动取出来用。
- 写法必须是
<script type="text/x-template" id="modal-terms"><div class="popup">...</div></script>,不能用template标签(它会解析内部资源) - 提取时用
document.getElementById('modal-terms').innerHTML,不是.textContent—— 后者会把标签当纯文本返回 - 插入后,
<img src="logo.png">会自动加载,但<img >不会,得手动补逻辑 - 里面写的
<script>console.log(1)</script>完全不会执行,这是安全边界,别指望它“活过来”
fetch() + innerHTML 注入静态 HTML 的实际限制
这是最直白的按需加载方式,但很多人卡在“为什么脚本没运行”“图片不加载”上——不是代码写错了,是浏览器行为本来就这样。
- 服务端必须返回**纯 HTML 片段**,不含
<html>、<body>外壳,否则innerHTML插入后可能破坏结构 -
<script>标签默认不执行,哪怕你用DOMParser解析后遍历插入,也得手动调用script.textContent或eval()(⚠️仅限可信源,否则 XSS 风险极高) -
<img src="a.jpg">会加载,但background-image: url(xxx)不会,因为样式规则没被解析;CSS 类名存在,但对应样式若未提前引入,就只是“有 class 没效果” - 事件监听器要自己绑定:不能靠 HTML 里的
onclick="xxx()",得用element.addEventListener('click', handler)
动态插入前用 DocumentFragment 避免强制重排
异步拿到 HTML 字符串后,别急着 el.innerHTML = html —— 尤其当目标容器已挂载且带 flex 或 grid 布局时,每插一个节点都可能触发一次 layout,卡顿明显。
- 正确做法:先
const frag = document.createDocumentFragment(),再循环创建节点并frag.appendChild(node),最后el.appendChild(frag) - 千万别先 push 到数组,再统一
appendChild—— 那还是 N 次独立插入,fragment 失效 - 如果插入前读了
el.offsetHeight,浏览器会提前 flush layout,fragment 优化就白做了 - 想对齐渲染帧?用
requestAnimationFrame(() => el.appendChild(frag)),但别把整个 for 循环包进去
为什么不要直接拼接 HTML 字符串再赋给 innerHTML
看似省事,实则埋下 XSS 和性能隐患。用户输入一旦混进字符串,onerror="alert(1)" 这类属性就会被执行。
立即学习“前端免费学习笔记(深入)”;
- 安全替代:用
document.createElement()+textContent(自动转义),比如li.textContent = user.name - 富文本场景必须用
DOMPurify.sanitize(htmlString)过滤,别信正则替换或简单白名单 - 性能代价:每次
innerHTML = ...都会销毁旧 DOM、重建新树、重新绑定事件,fragment 方案能避免反复销毁重建 - 调试困难:拼接字符串出错时,浏览器报错指向
innerHTML行,而不是原始数据源,定位成本高



















