真正可用的JSON编辑器应基于contenteditable实现语法着色、AST驱动缩进、递归DOM折叠、顺序保留序列化及移动端长按拦截。

用 contenteditable 做可编辑的 JSON 结构,别直接改 textarea
纯 textarea 无法高亮、折叠、实时校验,用户一输错就整个 JSON 报红,体验极差。真正可用的 JSON 编辑器必须支持语法着色和结构感知——最轻量可行的方式是用 contenteditable="true" 的 div 渲染带 class 的 HTML 片段,把每个 token(字符串、数字、冒号、逗号等)包裹成 span 并加语义类名,比如 json-string、json-number。
关键点:
- 不要监听
input事件做逐字解析——性能崩得快,尤其大 JSON;改用blur或防抖后的input触发全量解析 - 每次渲染前先用
JSON.parse()校验合法性,失败就回退到上一个合法状态,避免界面和数据不一致 - 缩进逻辑必须基于 AST(比如用
fast-json-parse或手写简易解析器提取层级),不能靠字符串replace(/ {2}/g)硬缩进
折叠节点必须靠递归生成 DOM,不能靠 CSS display: none 切换
JSON 里对象和数组可能嵌套十几层,用户需要点击「▶」展开某一层。如果只用 CSS 控制子节点显隐,DOM 仍完整存在,超深结构下内存暴涨、滚动卡顿。
正确做法是:解析时构建带 children 和 isCollapsed 字段的树形数据,渲染时仅对非折叠节点递归生成子 DOM。
示例逻辑片段:
function renderNode(node) {
if (node.type === 'object' && node.isCollapsed) {
return <span class="json-toggle">▶</span>
+ <span class="json-object">{…}</span>;
}
// 否则递归 render node.children
}
注意:isCollapsed 状态要持久化在节点数据上,而不是靠 class 切换——否则折叠后再编辑,新增字段容易丢失或错位。
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
JSON.stringify() 不能直接用于格式化输出,会丢键名顺序和注释
浏览器原生 JSON.stringify(obj, null, 2) 看似方便,但它强制按字典序重排 key,且彻底抹掉所有注释(哪怕你用非标准方式存了)。真实场景中,用户常依赖字段顺序表达业务含义(如配置文件),或临时加 // 注释调试。
解决方案分两路:
- 若需兼容注释 → 改用
comment-json库解析/序列化,它保留注释并维持 key 顺序 - 若只要顺序 → 手动遍历对象 keys(
Object.keys(obj)),不用for...in,再拼接字符串,避开stringify的排序陷阱 - 千万别在编辑器里显示「格式化后」内容却保存「原始输入」——前后端拿到的 JSON 字段顺序不一致,后续 diff 工具全失效
移动端长按选中文本会触发系统菜单,必须拦截 touchstart + preventDefault
在 iOS Safari 或安卓 Chrome 上,用 contenteditable 实现的编辑器,用户长按想选中某个字符串时,系统会弹出「复制/查找」菜单,遮挡折叠按钮,还可能意外触发文字放大镜。
解决方法不是禁用所有触摸事件,而是精准拦截:
- 给编辑容器绑定
touchstart,检测是否点在可交互区域(如折叠图标、括号)外 - 若点在纯文本 token 上,且
event.target.tagName === 'SPAN'且 class 含json-,则event.preventDefault() - 同时设
user-select: text在 token 元素上,确保短按仍可选中,只是屏蔽长按默认行为
这个细节在桌面端无关紧要,但上线后 70% 的吐槽来自 iPad 用户——他们真会拿手指点着 JSON 调试。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










