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

HTML中特殊符号显示异常,90%以上是编码设置与字符转义混用导致的,不是字体或缓存问题。
为什么、<code>&直接写会破坏DOM结构
浏览器解析器在data state下遇到&,会立刻切换到character reference state,等待合法实体名(如amp;、lt;)或数字引用(如)。若后面跟的是<code>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的实体字符串(即<code>"5 ),必须用<code>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返回<p>hello</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill11445" title="使用华数设计生成高保真HTML原型、演示文稿、动画和设计评审"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20e695c2374.jpg" alt="使用华数设计生成高保真HTML原型、演示文稿、动画和设计评审" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill11445" title="使用华数设计生成高保真HTML原型、演示文稿、动画和设计评审">使用华数设计生成高保真HTML原型、演示文稿、动画和设计评审</a>
<p>使用经过文档化的设计技能,从真实的品牌或项目背景中生成HTML原生原型、幻灯片、动态演示、可视化图表和评审流程。</p>
</div>
<a href="/xiazai/skill11445" title="使用华数设计生成高保真HTML原型、演示文稿、动画和设计评审" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div>
<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>,前端再用he.encode()处理,结果就是<p>hello</p>,页面原样输出标签源码。
- 推荐约定:传输层不转义,展示层按需转义。API响应保持原始字符串,前端在插入前判断上下文决定是否转义
- React用
dangerouslySetInnerHTML时,值必须是未转义的原始HTML;Vue用v-html同理 - Node.js用
he.encode(str, { useNamedReferences: true }),避免这类难读的数字实体
meta charset声明失效的典型场景
<meta charset="UTF-8">只在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在数据库里存的是原始内容,接口返回却悄悄做了转义,而前端又默认再转一次——三层嵌套后,连&都变成了&。这种问题不会报错,只会静默失效。


















