应使用 textarea 而非 contenteditable,因其原样保留代码字符;格式化须用 Prettier 浏览器版并显式指定 parser;需手动保存/恢复光标位置;资源需预加载且避免主线程阻塞。

为什么直接用 contenteditable 无法触发格式化
很多开发者尝试给 <div contenteditable="true"> 绑定 oninput 后调用 Prettier 或 Prism,结果发现粘贴进来的代码缩进混乱、换行丢失、甚至标签被浏览器自动闭合。根本原因是:contenteditable 编辑的是 HTML 片段,不是纯文本;浏览器会主动解析、修正、规范化 DOM 结构,导致原始代码字符串被破坏。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 必须使用
<textarea>作为输入容器——它原样保留换行、空格、尖括号,是代码编辑的唯一可靠入口 - 格式化前先用
textarea.value获取纯文本,别读innerHTML或innerText - 格式化后写回
textarea.value,而不是 innerHTML;否则<会被转义成 - 如果非要渲染高亮预览,另起一个只读
<pre><code>区域,用Prism.highlight处理,和编辑区物理隔离
用 Prettier 浏览器版一键格式化 HTML/JS/CSS
Prettier 是目前最稳定的前端代码格式化工具,其浏览器版本(prettier/standalone + prettier/parser-html 等)可直接在页面运行,无需服务端。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 通过 CDN 引入必需资源:
https://unpkg.com/prettier@3.2.5/standalone.js和对应 parser,例如 HTML 解析器用https://unpkg.com/prettier@3.2.5/parser-html.js - 调用时必须显式指定
parser,否则默认按 JS 解析,HTML 会报错Unexpected token "<" - 关键参数别漏:
printWidth: 80控制换行宽度,tabWidth: 2设缩进,useTabs: false避免混用空格/制表符 - 错误捕获要写实:Prettier 格式化失败时抛
Error,不是返回空字符串,需用try/catch捕获并提示用户具体哪一行出错
const formatted = prettier.format(dirtyCode, {
parser: "html",
plugins: [html],
printWidth: 80,
tabWidth: 2,
useTabs: false
});
点击按钮就格式化,但光标位置丢了怎么办
用户在中间修改一段代码后点“格式化”,结果光标跳到开头或末尾,接着输入内容全插错位置——这是最影响体验的细节问题。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 格式化前用
textarea.selectionStart和selectionEnd记录当前选区范围 - 格式化后不能直接
textarea.value = formatted,否则光标重置;要用setSelectionRange手动恢复 - 更稳妥的做法:把光标所在行提取出来,格式化整段后再计算新位置偏移量;或者干脆不恢复——改用“格式化后自动全选”,让用户明确知道内容已变
- 若支持多光标或块选中,优先保留选区长度,再按比例映射到新字符串中的大致位置(简单线性插值即可,不必 100% 精确)
为什么本地跑得好,部署后格式化变慢或卡死
常见现象:开发时点一下立刻完成,上线后点一次转圈 2 秒以上,甚至浏览器无响应。问题不在代码逻辑,而在资源加载与执行时机。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- Prettier 浏览器版体积大(standalone.js 超 1MB),首次执行要解析 AST,务必提前加载,不要等点击才
import() - 避免在主线程同步执行:长代码(>1000 行)格式化会阻塞 UI;可用
setTimeout(..., 0)微任务让渡控制权,或封装为Promise配合await - 移动端尤其注意:Safari 对 eval 类操作限制严格,
prettier/standalone内部用Function构造函数生成解析器,iOS 15+ 可能报DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope';此时应降级为服务端格式化或禁用该功能 - 缓存 parser 实例:同一语言的 parser 不必每次重载,初始化后复用可提速 30% 以上
复杂点在于,格式化不是纯函数调用,它依赖加载顺序、运行环境限制、用户输入状态三者耦合;漏掉任一环节,都会从“点一下就好”变成“点一下怀疑人生”。



















