基于CodeMirror 6实现实时代码编辑器:监听与同步变更求助
CodeMirror 6 实时代码同步实现方案
核心思路
CodeMirror 6 通过状态更新监听捕获所有文档变更(输入、删除、剪切、粘贴均会触发文档状态变更),再将变更内容通过编辑器视图的dispatch方法同步到目标实例。需要注意避免循环同步(比如A同步到B后,B的变更又触发回A)。
实现步骤与代码示例
1. 依赖准备
确保安装必要的包:
npm install @codemirror/react @codemirror/basic-setup @codemirror/lang-javascript
2. React 组件实现
import { useRef, useState } from 'react'; import { CodeMirror } from '@codemirror/react'; import { EditorState, basicSetup } from '@codemirror/basic-setup'; import { javascript } from '@codemirror/lang-javascript'; function SyncEditor() { // 存储两个编辑器的视图实例 const editor1Ref = useRef(null); const editor2Ref = useRef(null); // 标记同步状态,防止循环触发 const [isSyncing, setIsSyncing] = useState(false); // 编辑器1变更同步到编辑器2 const syncToEditor2 = (view) => { if (isSyncing) return; setIsSyncing(true); const changes = view.state.changes; if (changes.length > 0 && editor2Ref.current) { editor2Ref.current.dispatch({ changes }); } setIsSyncing(false); }; // 编辑器2变更同步到编辑器1(双向同步需保留,单向可删除) const syncToEditor1 = (view) => { if (isSyncing) return; setIsSyncing(true); const changes = view.state.changes; if (changes.length > 0 && editor1Ref.current) { editor1Ref.current.dispatch({ changes }); } setIsSyncing(false); }; // 生成编辑器配置 const getEditorConfig = (onDocChange) => ({ extensions: [ basicSetup, javascript(), // 监听文档状态变更 EditorState.updateListener.of((update) => { // 仅当文档内容改变时触发同步 if (update.docChanged) { onDocChange(update.view); } }) ], // 保存编辑器视图引用 onCreate: (view) => { editor1Ref.current ? (editor2Ref.current = view) : (editor1Ref.current = view); } }); return ( <div style={{ display: 'flex', gap: '20px', padding: '20px' }}> <div style={{ flex: 1 }}> <h3>源编辑器</h3> <CodeMirror {...getEditorConfig(syncToEditor2)} /> </div> <div style={{ flex: 1 }}> <h3>目标编辑器</h3> <CodeMirror {...getEditorConfig(syncToEditor1)} /> </div> </div> ); } export default SyncEditor;
关键细节说明
- 变更捕获:通过
EditorState.updateListener.of注册监听器,update.docChanged会在文档内容发生任何修改(输入、删除等)时返回true,此时可获取到具体的变更集合view.state.changes。 - 同步执行:调用目标编辑器视图的
dispatch({ changes })方法,将变更直接应用到目标文档,实现内容同步。 - 循环避免:使用
isSyncing状态标记同步过程,同步期间忽略新的变更触发,防止两个编辑器互相触发同步循环。
内容的提问来源于stack exchange,提问作者Shayantan Kabiraj
相关产品推荐
相关产品推荐

