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

如何在React Monaco Editor中手动刷新自定义Code Lens?

解决方案

1. 适配异步的getLenses方法

provideCodeLenses支持返回Promise类型,直接将其改为异步函数,通过await等待getLenses的异步结果即可:

{
  async provideCodeLenses(model: monaco.editor.ITextModel, token: monaco.CancellationToken): Promise<monaco.languages.CodeLensList> {
    const lenses: monaco.languages.CodeLens[] = [];
    // 等待异步方法返回结果
    const asyncLenses = await getLenses();
    lenses.push(...asyncLenses);
    
    // 可选:检查请求是否已取消,避免无效操作
    if (token.isCancellationRequested) {
      return { lenses: [], dispose: () => {} };
    }

    return {
      lenses,
      dispose: () => {},
    };
  },
}

2. 手动触发Code Lens刷新

利用Code Lens Provider的onDidChangeCodeLenses属性,结合monaco的Emitter实现手动刷新逻辑:

步骤1:创建持久化的Emitter实例

在React组件中用useRef保存Emitter,避免每次渲染重建:

import * as monaco from 'monaco-editor';

const codeLensEmitter = useRef(new monaco.Emitter<void>()).current;

步骤2:配置Provider的事件监听

注册Code Lens Provider时,绑定Emitter的事件:

const providerDisposable = monaco.languages.registerCodeLensProvider('your-language-id', {
  async provideCodeLenses(model, token) {
    // 同上述异步实现
    const asyncLenses = await getLenses();
    return { lenses: asyncLenses, dispose: () => {} };
  },
  // 暴露事件供外部触发刷新
  get onDidChangeCodeLenses() {
    return codeLensEmitter.event;
  },
});

步骤3:异步操作完成后触发刷新

在onChange回调的异步逻辑结束后,调用fire()触发Code Lens重新计算:

const onChange = async (value) => {
  // 执行你的异步业务操作
  await yourAsyncBusinessLogic(value);
  // 触发Code Lens刷新
  codeLensEmitter.fire();
};

步骤4:组件卸载时清理资源

避免内存泄漏,在组件卸载时销毁Provider和Emitter:

useEffect(() => {
  return () => {
    providerDisposable.dispose();
    codeLensEmitter.dispose();
  };
}, [providerDisposable, codeLensEmitter]);

完整示例片段

import React, { useRef, useEffect } from 'react';
import { MonacoEditor } from '@monaco-editor/react';
import * as monaco from 'monaco-editor';

const CustomEditor = () => {
  const codeLensEmitter = useRef(new monaco.Emitter<void>()).current;
  let providerDisposable = null;

  useEffect(() => {
    // 注册Code Lens Provider
    providerDisposable = monaco.languages.registerCodeLensProvider('javascript', {
      async provideCodeLenses(model, token) {
        // 模拟异步获取lenses的逻辑
        const asyncLenses = await new Promise((resolve) => {
          setTimeout(() => {
            resolve([
              {
                range: model.getFullModelRange(),
                command: {
                  id: 'custom-codelens',
                  title: '异步生成的Code Lens',
                },
              },
            ]);
          }, 300);
        });

        if (token.isCancellationRequested) {
          return { lenses: [], dispose: () => {} };
        }

        return { lenses: asyncLenses, dispose: () => {} };
      },
      get onDidChangeCodeLenses() {
        return codeLensEmitter.event;
      },
    });

    // 清理资源
    return () => {
      providerDisposable?.dispose();
      codeLensEmitter.dispose();
    };
  }, [codeLensEmitter]);

  const onChange = async (value) => {
    // 模拟业务异步操作
    await new Promise((resolve) => setTimeout(resolve, 800));
    // 触发Code Lens刷新
    codeLensEmitter.fire();
  };

  return (
    <MonacoEditor
      language="javascript"
      onChange={onChange}
      value="// 编辑内容后触发异步操作,完成后刷新Code Lens"
      height="400px"
    />
  );
};

export default CustomEditor;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:05:46