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

如何在@monaco-editor/react中配置模型监听器使DiagnosticsAdapter生效?

解决方案

问题的核心是Monaco Editor实例不一致以及模型创建时机不匹配,以下是修复步骤:

1. 修改DiagnosticsAdapter,接收外部传入的Monaco实例

不再直接import monaco,而是通过构造函数注入Editor组件提供的实例,确保监听器注册到正确的实例上:

import type * as Monaco from "monaco-editor";

export class DiagnosticsAdapter {
  private _disposables: Monaco.IDisposable[] = [];
  private _listener = Object.create(null);
  private monaco: typeof Monaco;

  constructor(monaco: typeof Monaco) {
    this.monaco = monaco;
    console.log("herehere in constructor");

    const onModelAdd = (model: Monaco.editor.IModel): void => {
      console.log("herehere onModelAdd");

      let handle;
      const changeSubscription = model.onDidChangeContent(() => {
        clearTimeout(handle);
        handle = setTimeout(() => console.log("call validation"), 500);
      });

      this._listener[model.uri.toString()] = {
        dispose() {
          changeSubscription.dispose();
          clearTimeout(handle);
        }
      };

      console.log("call validation");
    };

    const onModelRemoved = (model: Monaco.editor.IModel): void => {
      console.log("herehere onModelRemoved");
      this.monaco.editor.setModelMarkers(model, "abc", []);
      const key = model.uri.toString();
      if (this._listener[key]) {
        this._listener[key].dispose();
        delete this._listener[key];
      }
    };

    console.log("herehere 5");
    this._disposables.push(this.monaco.editor.onDidCreateModel(onModelAdd));
    console.log("herehere 6");
    this._disposables.push(this.monaco.editor.onWillDisposeModel(onModelRemoved));
    console.log("herehere 7");
    this._disposables.push(
      this.monaco.editor.onDidChangeModelLanguage((event) => {
        console.log("herehere 8");
        onModelRemoved(event.model);
        console.log("herehere 9");
        onModelAdd(event.model);
      })
    );

    console.log("herehere 10");
    this._disposables.push({
      dispose() {
        for (const model of this.monaco.editor.getModels()) {
          onModelRemoved(model);
        }
      }
    });

    console.log("herehere 11");
    // 手动处理已存在的模型(onMount触发时模型已创建)
    this.monaco.editor.getModels().forEach(onModelAdd);
  }

  public dispose(): void {
    this._disposables.forEach((d) => d && d.dispose());
    this._disposables = [];
  }
}

2. 在App组件中传递Monaco实例并管理适配器生命周期

将onMount回调中拿到的Monaco实例传入DiagnosticsAdapter,同时用useRef保存实例,在组件卸载时销毁以避免内存泄漏:

import React, { useRef, useEffect } from "react";
import Editor from "@monaco-editor/react";
import { DiagnosticsAdapter } from "./language-feature";

function App() {
  const adapterRef = useRef(null);

  function handleEditorDidMount(editor, monaco) {
    monaco.languages.register({ id: "mySpecialLanguage" });
    // 将Editor提供的monaco实例传入适配器
    adapterRef.current = new DiagnosticsAdapter(monaco);
  }

  // 组件卸载时销毁适配器
  useEffect(() => {
    return () => {
      if (adapterRef.current) {
        adapterRef.current.dispose();
      }
    };
  }, []);

  return (
    <div className="App">
      <Editor
        height="90vh"
        defaultLanguage="mySpecialLanguage"
        defaultValue="// some comment"
        onMount={handleEditorDidMount}
      />
    </div>
  );
}

export default App;

关键原因说明

  • 实例一致性:@monaco-editor/react内部维护独立的Monaco实例,直接从monaco-editor包import的实例和组件使用的实例不共享状态,导致监听器无法捕获事件。通过构造函数注入实例解决该问题。
  • 模型时机:Editor组件在onMount回调触发前已完成模型创建,因此需要手动遍历已存在的模型并执行onModelAdd,确保已有模型被处理。

内容的提问来源于stack exchange,提问作者SoftTimur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:24:52