能不用字符串拼接html就别用,尤其涉及用户输入——xss风险高、可维护性差、dom更新效率低;应优先用textcontent、documentfragment或框架转义机制,避免手动拼接。

直接说结论:能不用就别用字符串拼接 HTML,尤其涉及用户输入时——XSS 风险高、可维护性差、DOM 更新效率低。
为什么 innerHTML 拼接容易出安全问题
很多人用 + 或模板字面量拼接 HTML,再塞进 innerHTML,比如:el.innerHTML = '<div>' + userName + '</div>'。只要 userName 来自用户输入(表单、URL 参数、localStorage),攻击者就能注入 <script>alert(1)</script> 这类代码。
- 浏览器会把
innerHTML的内容当作 HTML 解析并执行,不做过滤 -
textContent是安全的替代,但它只写纯文本,不解析标签 - 若必须渲染动态 HTML,优先用
DOMParser或框架的转义机制,而不是手动拼接
createElement + appendChild 性能真的比字符串慢?
老说法是“字符串拼接快,DOM 操作慢”,但现代浏览器对小规模 DOM 构建优化很好;真正拖慢的是频繁触发重排(reflow)。关键不在“创建”本身,而在“插入时机”。
- 单次插入多个节点时,用
DocumentFragment批量操作,避免多次重排 - 不要在循环里反复写
el.appendChild(...),先建好 fragment 再一次性 append - 如果只是更新文本内容,
textContent比innerHTML快且安全 - 示例:
const frag = document.createDocumentFragment(); items.forEach(i => { const div = document.createElement('div'); div.textContent = i; frag.appendChild(div); }); el.appendChild(frag);
模板字符串里写 HTML 算不算“拼接”?
算,而且风险一样。ES6 模板字符串只是语法糖,`<div>${name}</div>` 和 '<div>' + name + '</div>' 在 DOM 注入场景下没有本质区别。
立即学习“前端免费学习笔记(深入)”;
- 模板字符串不会自动转义,
${}里的变量照原样插入 - 如果变量含 HTML 字符(如
、<code>"),浏览器照样解析成标签或破坏结构 - 想安全插值,得自己封装转义函数,比如:
function escapeHtml(str) { return str.replace(/[&"'/]/g, c => ({'&': '&', '': '>', '"': '"', "'": ''', '/': '/'}[c])); } - 更稳妥的做法:用
textContent设内容,用setAttribute设属性,完全绕过 HTML 解析
最常被忽略的一点:不是“能不能拼”,而是“有没有必要拼”。很多场景下,用 classList.toggle 控制显隐、用 dataset 存数据、用 CSS 变量控制样式,比拼一整段 HTML 更轻、更可控、也更不容易漏掉转义。










