解决monaco-editor中registerCompletionItemProvider多次注册导致展示的提示内容重复问题

目录
文章目录隐藏
  1. 遇到的问题以及解决办法

最近项目实现一个提示功能,输入某个符号,展示匹配的内容,和代码提示功能类似。最终选择了monaco-editor,微软开发的 js 库,vscode也是基于这个库开发的。

在开发过程中,遇到些问题,由于文档不是很友好,花了半天才解决问题。下面主要记录一下问题以及解决办法,希望以后遇到这些问题的童鞋能快速避坑。

遇到的问题以及解决办法

问题:

在 Antd Modal 中使用 monaco-editor,显示 Modal 后关闭 Modal,再次打开 Modal,monaco-editor 的提示内容就会重复,显示几次 Modal,对应的内容就会重复几次,如下图:

使用 monaco-editor,registerCompletionItemProvider 多次注册,最终导致展示的提示内容重复

解决办法

思路 1:

经过调试发现,registerCompletionItemProvider方法多次执行,首先猜到的可能是插件多次创建,没有销毁造成的,查阅对应的文档后,发现有插件提供了一个销毁的方法:

monaco.editor.dispose()

于是,尝试在组件销毁之前调用上面的方法,但是运行后发现并不生效,上述问题依旧存在,此法不通~

思路 2:

既然registerCompletionItemProvider多次执行,那么给组件中添加一个全局的计数器 count,组件注册一次后执行一次 count+1,只有当 count===0 时,才走对应的插件注册逻辑,否则直接取缓存的数据。部分代码片段如下:

 let count = 0;
      monaco.languages.registerCompletionItemProvider(languageName, {
        triggerCharacters: ['['],
        provideCompletionItems: function (model, position, context) {
          count=count+1;
          if(count===1){
            let suggestions = [];
            if (context.triggerCharacter === '[') {
              [...dimensions, ...modules].forEach((item, index) => {
                suggestions.push({
                  label: item.customName,
                  insertText: `${item.customName}]`,
                  kind: 12,
                });
              });
            }
            return { suggestions };
          }
        },
      });

这种方式简单粗暴,如果需要插件提示的内容是固定的,直接用缓存的数据是可以解决这个问题。但是!!!我遇到的需求是,提示的内容是根据接口动态取的。所以,此法依旧不通~

思路 3:

由于谷歌和百度都没用找到满意的答案,于是去monaco-editorGitHub 的 issues中查找答案,刚开始根据registerCompletionItemProvider关键字搜索,但是并没有类似的问题,然后又尝试搜索provideCompletionItems关键词,最终在 issues 中找到了 2 个类似的问题,如下:使用 monaco-editor,registerCompletionItemProvider 多次注册,最终导致展示的提示内容重复

使用 monaco-editor,registerCompletionItemProvider 多次注册,最终导致展示的提示内容重复

 

最终解决办法:

registerCompletionItemProvider注册创建时,将创建的对象存储起来,如下:

monacoProviderRef.current = monaco.languages.registerCompletionItemProvider(languageName, {

在组件销毁时,将editorregisterCompletionItemProvider生成的对象一同销毁。代码如下:

useEffect(() => {
      // todo
      // xxxxxx
      return () => {
        // 销毁
        monacoProviderRef.current?.dispose();
        monacoRef.current?.dispose();
        
      };
    }, []);

最后测试,bug 完美解决!

问题:

设置 editor 的默认主题,但是 Modal 第一次展示时,默认主题没有生效,第一次之后主题才会生效,如下图:

设置 editor 的默认主题

设置默认主题代码如下:

monaco.editor.defineTheme('myCoolTheme', {
    base: 'vs',
    inherit: false,
    colors: { token: 'value', foreground: '#00c1de' },
    rules: [{ token: 'value', foreground: '#00c1de' }],
});

解决办法

去官方文档中找设置主题的 api,发现以上代码是对主题的定义操作,如果要首次运行生效,还需要手动设置一次上面对应定义的主题

monaco.editor.setTheme('myCoolTheme');

最终,问题解决,效果如下:

设置主题的 api

原文链接:点击这里

「点点赞赏,手留余香」

3

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 解决monaco-editor中registerCompletionItemProvider多次注册导致展示的提示内容重复问题

发表回复