如何在monaco editor中不使用分栏DiffEditor显示修改行的diff差异
Monaco Editor单行版行内变更标记实现方案
完全可以实现该需求,不需要使用分栏DiffEditor,核心结合monaco内置的diff计算能力和编辑器装饰器API即可对齐VS Code的行内变更提示体验。

具体实现步骤如下:
- 调用内置diff计算接口得到差异结果
无需引入第三方diff库,直接使用monaco.diff.computeDiff(基准文本, 当前文本, { ignoreTrimWhitespace: false })即可得到结构化的差异数据,包含新增、修改、删除的行范围以及字符级差异明细。 - 定义对齐VS Code风格的装饰器配置
三类变更对应不同的装饰器规则:- 新增行:左侧gutter展示绿色竖条,整行加极淡绿色背景
- 修改行:左侧gutter展示黄色竖条,行内差异字符分别标记淡红(删除内容)、淡绿(新增内容)背景
- 删除行:在对应相邻行的gutter上方展示红色小三角,可配置悬停提示展示被删除的原文内容
- 绑定事件实现实时更新
监听编辑器onDidChangeModelContent事件,每次内容变更后重新计算diff,调用editor.deltaDecorations()方法批量更新所有变更标记即可。
简化实现代码参考:
// 初始化三类变更的装饰器集合 const diffDecorations = { added: editor.createDecorationsCollection(), modified: editor.createDecorationsCollection(), deleted: editor.createDecorationsCollection() } // 装饰器样式配置(对应CSS可自行对齐VS Code配色) const DECORATION_CONFIG = { added: { isWholeLine: true, linesDecorationsClassName: 'diff-line-added-gutter', className: 'diff-line-added-content' }, modified: { isWholeLine: true, linesDecorationsClassName: 'diff-line-modified-gutter', className: 'diff-line-modified-content' }, deleted: (lineNum, delContent) => ({ range: new monaco.Range(lineNum, 1, lineNum, 1), linesDecorationsClassName: 'diff-line-deleted-gutter', hoverMessage: { value: `已删除内容:\n${delContent}` } }) } // 更新变更标记的核心方法 function refreshDiffMarkers(originalText, currentText) { const diffResult = monaco.diff.computeDiff(originalText, currentText) const addedDecos = [], modifiedDecos = [], deletedDecos = [] // 遍历diff结果组装对应装饰器配置 // diffResult.changes中每个项都包含originalStartLine、originalEndLine、modifiedStartLine、modifiedEndLine等属性,可直接用于构造Range diffDecorations.added.set(addedDecos) diffDecorations.modified.set(modifiedDecos) diffDecorations.deleted.set(deletedDecos) }
如果需要完全对齐VS Code的交互细节,只需要调整装饰器对应的CSS样式、增加点击跳转变更等交互逻辑即可,核心实现逻辑不需要额外调整。
内容的提问来源于stack exchange,提问作者Sandesh Baliga
相关产品推荐
相关产品推荐

