pre标签本身不修复格式,只忠实地渲染收到的字符;换行和空格不显示,是因为内容在抵达pre前已被转义、折叠或丢失真实 ,如后端双重转义为"line1 line2"或innerhtml拼接未解析换行符。

pre 标签本身不“修复”格式,只忠实地渲染它收到的字符——如果看到换行和空格没生效,问题一定出在内容抵达 pre 之前就已丢失或被转义。
为什么 pre 里换行和空格不显示
浏览器默认会把连续空白(包括
、 、多个空格)压缩成一个空格,而 pre 的作用只是“不主动折叠”,但它无法还原已被吃掉的换行符。常见断点:
- 后端返回 JSON 字段中是字符串
"line1\nline2"(两个反斜杠),JS 解析后得到的是字面量"line1 line2",不是真实换行 - 前端用
innerHTML拼接:el.innerHTML = "<pre class="brush:php;toolbar:false;">" + str + "</pre>",若str含未转义的或 <code>&,会被 HTML 解析器截断或误解析 - Vue 中写
{{ text }}、React 中用{text}但服务端返回的是 HTML 转义后的,而非原生 - CSS 被重置:全局
* { white-space: normal; }直接覆盖了pre默认的white-space: pre
动态注入必须用 textContent
这是最常被跳过的一步。只要内容来自 API、用户输入或 JS 变量,就别碰 innerHTML。
- 正确:
preEl.textContent = apiResponse.body—— 绕过 HTML 解析,保留所有原始空白 - 错误:
preEl.innerHTML = apiResponse.body—— 若响应含,可能被当标签解析;若含 <code>字面量,它就真显示成文字 - React/Vue 中:
{text}和v-text="text"默认走textContent,安全;但v-html或dangerouslySetInnerHTML会触发 HTML 解析,禁用
必须配齐三样 CSS 才算真正生效
只写 <pre class="brush:php;toolbar:false;">...</pre> 是不够的。现代项目中 reset.css、字体 fallback、容器宽度都会破坏效果。
-
white-space: pre-wrap—— 比默认pre更实用:保留缩进与空格,同时允许长行自动折行(避免横向撑破) -
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, 'Microsoft YaHei Mono', monospace—— 显式声明中英文等宽字体栈,防中文缩进塌陷 -
overflow-x: auto; max-width: 100%—— 横向滚动必须配对父容器宽度限制,否则滚动条不触发 - 额外建议:
tab-size: 4统一制表符宽度,避免编辑器差异导致错位
展示代码时务必提前转义 和 <code>&
pre 不做任何过滤,它照单渲染你给的每个字符。如果后端返回的是未转义的 <div>hello</div>,浏览器会尝试解析这个标签,轻则内容消失,重则破坏整个 DOM。
- 可信来源(如自己写的示例):用
DOMPurify.sanitize()或textContent注入前手动转义:str.replace(/, ' - 不可信来源(如日志 API):宁可全用
textContent,也别冒险innerHTML - 注意:不要对已含
实体的字符串重复转义,否则变成 <code><
真正难的不是加个 pre 标签,而是从数据源头(服务端编码)、传输过程(JSON 序列化方式)、前端接收(是否二次 JSON.stringify)、到 DOM 注入(textContent 还是 innerHTML)全程守住
和连续空格的“真实性”。中间任何一环出问题,pre 都救不回来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











