用template元素+clonenode(true)替代innerhtml+=是效率陷阱,易引发引号嵌套错、[object object]、xss、dom重排;必须用document.createelement('template')创建模板,每次插入调用template.content.clonenode(true),避免直接appendchild导致模板清空。

用 template 元素 + cloneNode(true) 替代 innerHTML +=
直接拼字符串写 HTML 是效率陷阱,不是提速手段。引号嵌套错、对象变 [object Object]、XSS 漏洞、DOM 频繁重排全会一起爆发。
- 必须用
document.createElement('template')创建模板,它不渲染、不执行脚本、不发请求,纯结构容器 - 每次插入都得调
template.content.cloneNode(true),直接appendChild(template.content)会把原节点移走,第二次就空了 - 模板里别放
<script></script>或<style></style>,它们不会生效;逻辑抽成函数,样式外置 CSS 文件 - 适合单次渲染几十条以内的内容,比如菜单项、弹窗表单、状态提示块
传数据别塞对象进 data- 属性
<div data-item="${item}"> 看似省事,但 <code>item 是对象时固定输出 [object Object];JSON.stringify(item) 又会把双引号、斜杠全转义,HTML 结构直接崩坏。
- 只插原始类型:如
item.name、item.price?.toFixed(2) - 需要整个对象?改用
data-id="123"存唯一标识,JS 里查表获取真实数据 - 调试真要序列化?走
fetch加载外部 HTML 片段时再注入,且仅限低频场景
加载外部 HTML 片段必须加 .catch()
用 fetch('/navbar.html').then(r => r.text()).then(html => el.innerHTML = html) 很干净,但网络失败、404、CORS 会导致目标区域彻底空白,用户看不到任何 fallback。
- 必须补上
.catch(() => el.innerHTML = '<!-- navbar load failed -->'),哪怕只是占位注释 - 不能在
DOMContentLoaded前操作目标元素,否则querySelector返回null - 片段里含内联
<script></script>?别指望自动执行——应把初始化逻辑抽成独立函数,加载完显式调用
Webpack 场景下优先用 html-webpack-template
手写 template 适合小模块动态渲染,但整页骨架生成还是交给构建工具更稳。直接配 html-webpack-plugin + html-webpack-template 能自动注入资源、管理 meta、隔离挂载点。
- 安装后在
webpack.config.js中配置template: require.resolve('html-webpack-template') - 支持
title、appMountId、meta数组等字段,不用手动写<title></title>或<meta name="viewport"> - 它会自动根据 Webpack 输出插入
<link>和<script></script>标签,避免手写路径出错或顺序混乱
真正卡住效率的从来不是“会不会写 template”,而是数据来源没对齐、错误没兜底、更新时机没控制——这三处松动,模板立刻变成维护黑洞。











