HTML中必须转义的只有&、、"、'这5个字符,因它们直接触发标签解析、实体识别或属性截断;未转义会导致DOM断裂、XSS漏洞或渲染异常,其中&最危险,会启动实体状态机并引发连锁解析错误。

HTML中特殊符号显示异常,90%以上是编码设置与字符转义混用导致的,不是字体或缓存问题。
为什么、&直接写会破坏DOM结构
&直接写会破坏DOM结构浏览器解析器在data state下遇到&,会立刻切换到character reference state,等待合法实体名(如amp;、lt;)或数字引用(如)。若后面跟的是name="John & Jane"这种孤立&,解析器会截断字符串、丢弃后续内容,甚至让整个innerHTML挂载失败。
- 常见错误现象:
href="page.php?id=1&name=test"→ 实际只传了id=1,&name=test消失 - JS中动态拼接:
onclick="do('a&b')"→ 引号提前闭合,报Uncaught SyntaxError - 服务端返回已转义字符串,前端又用
he.encode()再套一层 → 页面显示而不是
textContent + innerHTML 是最安全的HTML编码方式
想把原始字符串(如"5 )变成可安全插入HTML的实体字符串(即"5 ),必须用textContent驱动innerHTML提取,不能反着来。
- 正确做法:
const temp = document.createElement('div'); temp.textContent = '5 - 绝对别用:
temp.innerHTML = raw; temp.textContent—— 这会执行HTML,有XSS风险 - 也别用
innerText:它受CSSdisplay:none影响,还会折叠空白符和换行,不可靠
服务端模板与前端渲染的双重转义陷阱
当Django/Jinja/Vue/React这类框架参与渲染时,「谁该负责转义」必须明确,否则极易嵌套转义。例如后端API返回 hello hello,前端再用he.encode()处理,结果就是,页面原样输出标签源码。
- 推荐约定:传输层不转义,展示层按需转义。API响应保持原始字符串,前端在插入前判断上下文决定是否转义
- React用
dangerouslySetInnerHTML时,值必须是未转义的原始HTML;Vue用v-html同理 - Node.js用
he.encode(str, { useNamedReferences: true }),避免这类难读的数字实体
meta charset声明失效的典型场景
只在HTML文件本身保存为UTF-8时才有效。如果文件用GBK保存,但写了UTF-8声明,浏览器仍会按声明解码——结果就是中文变问号或乱码方块。
- 检查顺序必须是:文件实际编码 → HTTP响应头
Content-Type→meta charset→ 浏览器自动识别(最不可靠) - VS Code保存时务必选
UTF-8 with BOM或UTF-8(无BOM),不要选UTF-8 with signature以外的其他选项 - Apache加
AddDefaultCharset UTF-8,Nginx配charset utf-8;,确保响应头优先级高于meta
最容易被忽略的是:前后端协作时,同一段HTML在数据库里存的是原始内容,接口返回却悄悄做了转义,而前端又默认再转一次——三层嵌套后,连&都变成了&。这种问题不会报错,只会静默失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











