textcontent 是默认安全选择,因为它把所有输入当字符串处理,自动转义尖括号、引号等字符,不解析标签、不执行脚本、不触发重排,天然防御 xss,且跨浏览器行为一致。

纯文本场景下,无条件用 textContent;只有必须解析 HTML 结构时,才考虑 innerHTML,且必须过滤。
为什么 textContent 是默认安全选择
textContent 把所有输入当字符串处理,、<code>&、" 全部转义为可见字符,不触发任何解析逻辑。它不会创建新节点,不销毁事件监听器,也不重置 input.value。
- 常见误用:
el.innerHTML = "用户说:" + userInput→ 一旦userInput是"<img onerror="alert(1)">",立刻弹窗 - 正确写法:
el.textContent = "用户说:" + userInput→ 页面原样显示那串带标签的文字 - 性能实测:在含 20+ 子节点的容器中连续更新 100 次,
textContent耗时通常只有innerHTML的 1/3~1/5 - 空白符保留严格:换行、缩进、多个空格都会照常渲染,适合日志、代码块、错误提示等场景
innerHTML 什么情况下非用不可
只有当你明确需要浏览器把字符串当作 HTML 解析并构建 DOM 节点时,innerHTML 才是合理选项——不是“能用”,而是“不得不”用。
- 典型场景:插入服务端返回的已过滤富文本(如后台编辑器输出)、动态生成带语义的提示(
el.innerHTML = "请检查 <strong>邮箱格式</strong>")、整块替换硬编码模板 - 关键前提:字符串中不能拼接任何未过滤的外部数据(用户输入、API 返回值、URL 参数)
- 高危信号:出现模板字符串拼接,如
el.innerHTML = `<div>${userInput}</div>`→ 和直接赋值无异,XSS 风险照旧 - HTML5 对
<script></script>标签有执行限制,但<img onerror="...">、<svg onload="..."></svg>、javascript:...仍可触发,正则手动过滤几乎必然被绕过
别拿 innerText 当 textContent 的备胎
innerText 不是更“友好”的替代品,它是行为不可控的陷阱。
- 受 CSS 影响:
display: none或visibility: hidden的子元素内容会被忽略,表格中表现尤其异常 - 自动折叠空白:多个空格、换行会被压缩成单个空格,无法还原原始格式
- 强制触发重排(reflow):首次读取会同步计算布局,影响性能,而
textContent完全不触发 - 跨浏览器不一致:IE、Edge、Chrome 在 contenteditable 或表格单元格中返回结果不同
- 截至 2026 年,所有主流框架与 OWASP 安全指南都明确建议:禁用
innerText作防 XSS 方案
真要渲染富文本?别自己造轮子
业务强依赖 HTML 输出时(比如评论区支持加粗、链接),innerHTML 本身没问题,但净化环节不能跳过。
- 必须用白名单库,如
DOMPurify.sanitize(htmlString),只保留p、strong、a等安全标签和属性 - 避免手写正则清洗 ——
<svg><script></script></svg>、<img src="x" onerror="...">这类变种极易漏掉 - 服务端也应做同样净化,前后端双重防护不能省
- 最稳妥的边界处理方式:结构化数据驱动渲染,例如把消息拆成
{ type: 'text', value: '你好' }和{ type: 'mention', id: '123', name: '@张三' },再由安全函数分别处理
真正难处理的从来不是“该用哪个 API”,而是业务里文本和 HTML 混杂的模糊地带——那里没有银弹,只有结构化、白名单、双重校验组成的防御纵深。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











