最近專案實現一個提示功能,輸入某個符號,展示匹配的內容,和程式碼提示功能類似。最終選擇了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!祝大家中秋節快樂!!!