pre里直接写

pre里直接写或会触发HTML解析
pre本身不阻止浏览器解析标签,它只保留空白符和换行。只要里面出现未转义的 <code> 或 <code>&,浏览器就会当成真实HTML处理——哪怕你本意只是展示一段带尖括号的代码。
常见错误现象包括:
- 原始代码里的
<div> 被吃掉,后续内容错位 <li> <code>pre块提前闭合,后面 DOM 结构全乱 - 手动插入的
<span class="keyword">if</span>被当成未闭合标签,触发浏览器自动补全,破坏高亮结构
根本原因不是 pre 有问题,而是你传给它的字符串里混入了未经转义的 HTML 字符。它忠实地渲染你给的内容,不管那是不是“你想显示的代码”。
必须用 <pre class="brush:php;toolbar:false;"> 嵌套,不能只用 <pre class="brush:php;toolbar:false;"> 或只用 <code></code>
单独用 pre:能保留缩进和换行,但语义缺失,屏幕阅读器无法识别这是代码块,CSS 也难精准选中;
单独用 code:它是行内元素,\n 和多余空格全被忽略,结果就是所有代码挤成一行。
正确结构只有这一种:
function a() {\n return 1;\n}。其中:
-
pre负责保留格式(换行、空格、\t) -
code负责声明语义(“这是计算机代码”,影响可访问性、SEO、CSS 选择器) -
class="js"是可选但强烈推荐,用于后续语法高亮或 JS 处理
动态插入时别用 innerHTML +=
对已有 pre 做增量操作(比如加高亮),直接改 innerHTML 极易出问题:
- 清空当前光标位置和用户 selection
- 已有的
span节点可能被重新解析,导致样式丢失或嵌套错乱 - 若拼接字符串时漏转义,
又会被当标签解析
更安全的做法是:
- 先用
element.textContent拿纯文本,避免误读已有标签 - 基于纯文本坐标算出高亮起止位置
- 用
Range+DocumentFragment精准包裹目标文本节点,不碰innerHTML
转义是硬性前提,CSS 或 JS 都救不了
HTML 解析阶段就发生的破坏,没有回旋余地。以下字符必须在插入前转义:
→ <code>-
>→> -
&→&
别指望 white-space: pre 或 Prism.js 自动帮你转——它们运行在 DOM 已构建之后,而解析错误早在那之前就毁了结构。动态生成时,务必先构建完整转义后的字符串,再一次性赋值给 innerHTML,而不是边拼边插。
最容易被忽略的一点:即使你用了 pre + code,只要漏转一个 &,整个代码块就可能从中间断裂,且这种错误在开发者工具里看不出明显报错,只能靠肉眼比对渲染结果和原始字符串。











