最近项目实现一个提示功能,输入某个符号,展示匹配的内容,和代码提示功能类似。最终选择了monaco-editor,微软开发的js库,vscode
也是基于这个库开发的。
在开发过程中,遇到些问题,由于文档不是很友好,花了半天才解决问题。下面主要记录一下问题以及解决办法,希望以后遇到这些问题的童鞋能快速避坑。
遇到的问题以及解决办法
问题:
在Antd Modal中使用monaco-editor,显示Modal后关闭Modal,再次打开Modal,monaco-editor的提示内容就会重复,显示几次Modal,对应的内容就会重复几次,如下图:
解决办法
思路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-editor
的GitHub
的 issues
中查找答案,刚开始根据registerCompletionItemProvider
关键字搜索,但是并没有类似的问题,然后又尝试搜索provideCompletionItems
关键词,最终在issues中找到了2个类似的问题,链接如下:
https://github.com/microsoft/monaco-editor/issues/2217
https://github.com/microsoft/monaco-editor/issues/2084
最终解决办法:
在registerCompletionItemProvider
注册创建时,将创建的对象存储起来,如下:
monacoProviderRef.current = monaco.languages.registerCompletionItemProvider(languageName, {
在组件销毁时,将editor
和registerCompletionItemProvider
生成的对象一同销毁。代码如下:
useEffect(() => {
// todo
// xxxxxx
return () => {
// 销毁
monacoProviderRef.current?.dispose();
monacoRef.current?.dispose();
};
}, []);
最后测试,bug完美解决!
问题:
设置editor的默认主题,但是Modal第一次展示时,默认主题没有生效,第一次之后主题才会生效,如下图:
设置默认主题代码如下:
monaco.editor.defineTheme('myCoolTheme', {
base: 'vs',
inherit: false,
colors: { token: 'value', foreground: '#00c1de' },
rules: [{ token: 'value', foreground: '#00c1de' }],
});
解决办法
去官方文档中找设置主题的api,发现以上代码是对主题的定义操作,如果要首次运行生效,还需要手动设置一次上面对应定义的主题
monaco.editor.setTheme('myCoolTheme');
最终,问题解决,效果如下:
愿天下没有难解的bug!祝大家中秋节快乐!!!