深入理解 < 和 >:HTML 实体转义的核心指南(2026 最新版)
< 和 > 是 HTML 中最危险也最容易被误用的两个字符。
不转义它们 → 立即引发 XSS(跨站脚本攻击);
转义错误 → 页面显示乱码、布局崩坏、SEO 失效。
下面是从原理 → 实战 → 安全 → 工具的完整闭环指南,2026 年前端(React / Vue / Svelte / Solid / Astro)必备。
1. 为什么必须转义?(核心原理)
HTML 解析器把以下 5 个字符视为特殊标记:
| 字符 | 原始含义 | 必须转义为实体 | 不转义后果 |
|---|---|---|---|
| < | 标签开始 | < | 被解析为标签 → XSS / 布局崩 |
| > | 标签结束(多数情况) | > | 在某些上下文引发解析错误 |
| & | 实体开始 | & | 后面字符被当成实体解析 |
| “ | 属性值双引号 | " | 属性提前闭合 |
| ‘ | 属性值单引号 | '(HTML5 可选) | 同上 |
历史根源:HTML 来自 SGML(1986),实体转义是“告诉解析器:这个字符是普通文本,不是标记”的唯一方式。
浏览器行为(2026 标准):
- 在文本节点(
<div>这里的内容</div>)中,<必须转义,否则解析器认为新标签开始。 - 在属性值中,
"和&必须转义。 >在大多数现代浏览器里可以不转义(HTML5 宽松),但强烈建议一直转义,防止旧浏览器 / XML / RSS / SVG 出错。
2. 完整实体转义表(前端日常够用 Top 12)
| 显示结果 | 实体写法 | 十进制 | 十六进制 | 备注 |
|---|---|---|---|---|
| < | < | < | < | 最重要 |
| > | > | > | > | 推荐始终转义 |
| & | & | & | & | 第二重要 |
| “ | " | “ | “ | 属性必转 |
| ‘ | ' | ‘ | ‘ | HTML5 支持 |
| 防止空格被合并 | |||
| © | © | © | © | 版权 |
| × | × | × | × | 乘号 |
| ÷ | ÷ | ÷ | ÷ | 除号 |
| — | — | — | — | 破折号 |
| … | … | … | … | 省略号 |
| € | € | € | € | 欧元 |
3. 不同上下文的正确转义方式(2026 实战)
3.1 纯 HTML / 模板
<!-- 正确 -->
<div>用户输入:<script>alert(1)</script></div>
<!-- 错误(XSS) -->
<div>用户输入:<script>alert(1)</script></div>
3.2 JavaScript 动态插入(最容易出错)
// ❌ 危险
element.innerHTML = userInput; // 直接拼接
// ✅ 推荐方式 2026
element.textContent = userInput; // 自动转义 < > &
// 或手动转义函数(兼容所有框架)
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
3.3 React(2026 推荐)
// 1. 最安全(推荐)
<div>{userInput}</div> // React 自动转义
// 2. 需要 HTML 时必须净化
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
3.4 Vue 3(2026)
<!-- 自动转义 -->
<div>{{ userInput }}</div>
<!-- 需要 HTML -->
<div v-html="sanitizedInput"></div> <!-- 必须先 DOMPurify -->
3.5 Svelte / Solid / Astro
- Svelte:
{@html ...}必须净化 - Solid:
<div innerHTML={...}>需净化 - Astro:默认安全,
set:html需手动净化
4. 常见坑 & 2026 年新问题
- Markdown 转 HTML:很多库(marked、remark)默认不转义 → 必须配合
sanitize。 - 模板字符串 + innerHTML:模板${userInput} → 仍需手动 escape。
- SVG / MathML 内嵌:
<和>在<svg>里也必须转义,否则解析失败。 - JSON 里包含 HTML:先 JSON.stringify,再 escapeHtml。
- CSP(Content-Security-Policy)严格模式:
unsafe-inline被禁用后,innerHTML直接失效,必须走 textContent + 实体。 - AI 生成代码(Cursor / Claude):AI 经常忘记转义 → 必须在 prompt 里加一句 “Always use escapeHtml for any user content”。
5. 生产级安全方案(推荐组合)
| 场景 | 推荐方案 | 一行代码示例 |
|---|---|---|
| 普通文本 | textContent / {{ }} | el.textContent = input |
| 需要富文本 | DOMPurify + 实体转义 | DOMPurify.sanitize(input, {ALLOWED_TAGS: [...]}) |
| 大规模渲染 | he 库(最快) | he.encode(input) |
| React 全站 | react-escape-html + DOMPurify | 全局拦截 |
| Node.js 服务端渲染 | sanitize-html | 服务端先净化再返回 |
最强组合(2026 共识):
npm install dompurify he
import DOMPurify from 'dompurify';
import he from 'he';
const safeHtml = he.encode(DOMPurify.sanitize(rawHtml));
6. 一句话总结 + 检查清单
核心原则:
- 所有用户输入在插入 DOM 前必须转义(或用框架自动机制)。
<和>是“告诉浏览器:我就是想显示 < 和 >”的唯一正确方式。- 永远不要相信“浏览器会自动处理”——它只在 textContent 里处理。
每日代码审查清单(复制到 Notion / Cursor Rule):
- [ ] 所有
innerHTML/v-html/dangerouslySetInnerHTML是否经过净化? - [ ] 所有用户内容是否走
textContent或escapeHtml? - [ ] Markdown / AI 生成的内容是否加了 sanitize?
- [ ] 测试输入:
<script>alert(1)</script>、<img src=x onerror=alert(1)>
掌握了 < 和 > 的实体转义,你就掌握了前端安全的第一道防线。
需要我立刻给你:
- 完整的
escapeHtml工具函数(支持 React/Vue/Svelte 多版本) - DOMPurify + Tailwind 的企业级配置模板
- 针对 Cursor / Claude 的防 XSS Prompt 模板
直接说场景,我 30 秒给你发完整代码!