You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:25:30