textContent用于纯文本,innerHTML仅用于需解析HTML的场景;混用易致XSS、DOM异常或性能问题;innerText非安全替代,应避免用作兜底。

关键不是“怎么写”,而是“为什么这么选”——textContent 用于纯文本,innerHTML 用于结构化 HTML,混用或误判会带来 XSS 风险、DOM 行为异常或性能损耗。
优先用 textContent 更新纯文本
90% 的动态文本场景(错误提示、标题、日志、昵称)只需显示文字,不需解析标签。此时 textContent 是默认首选:
- 自动转义所有 HTML 字符:
<script>alert(1)</script>会原样显示,不会执行 - 不触发重排,不重置 input 的 value,不丢失事件监听器
- 保留空白和换行,行为跨浏览器一致,W3C 标准推荐
- 示例:
errorEl.textContent = "密码不能少于6位"、titleEl.textContent = userTitle
仅当真需渲染 HTML 时才用 innerHTML
只有内容含语义标签(如 <strong>、<a>、<br>),且你明确需要浏览器解析并构建 DOM,才考虑 innerHTML:
- 动态插入带格式的提示:
el.innerHTML = "请检查 <strong>邮箱格式</strong> 并重试" - 渲染服务端返回的轻量富文本(但前提是已过滤)
- 整块替换静态模板:
box.innerHTML = "<h2>欢迎页</h2><p>点击开始</p>" - ⚠️ 一旦拼接任何外部数据(用户输入、API 返回、URL 参数),立刻高危
处理不可信富文本:别手写过滤,用白名单净化
正则删 <script> 或 onxxx 属性几乎必然被绕过。真实攻击常藏在 SVG 事件、javascript: 协议、CSS 表达式中:
立即学习“Java免费学习笔记(深入)”;
- 前端用
DOMPurify.sanitize(dirtyHtml, { ALLOWED_TAGS: ['p','strong','br'], ALLOWED_ATTR: ['class'] }) - 服务端应在 API 返回前就净化(如 Node.js 的
sanitize-html),前端只负责渲染 - 替代路径:将富文本转为 Markdown 渲染;或用
<template>+cloneNode()手动填值,彻底避开字符串拼接
别用 innerText 当安全兜底
innerText 不是 textContent 的“兼容版”,而是逻辑不同的属性:
- 受 CSS 影响(
display: none的文字不计入)、自动折叠空白、在表格中行为异常 - 某些 Safari 版本会强制触发 layout 计算,影响性能
- 在
<input>或<textarea>上读取的是“渲染后可见文本”,非真实值 - 仅在需兼容 IE8 等极老旧环境时,才考虑
el.innerText || el.textContent回退



















