您好,登錄后才能下訂單哦!
這次接到一個需求,要在瀏覽器的 IDE
中支持自定義提示功能,如下所示:
可以看到,它可以根據用戶輸入的內容來一項一項排除,只顯示完全匹配的那一項。
項目的框架是 Vue
,編輯器用的是 Monaco Editor
。
什么是 Monaco Editor
vscode
是我們經常在用的編輯器,它的前身是微軟的一個叫 Monaco Workbench
的項目,而 Monaco Editor
就是從這個項目中成長出來的一個 web
編輯器,他們很大一部分的代碼都是共用的,所以 Monaco Editor
和 VSCode
在編輯代碼,交互及 UI
上幾乎是一摸一樣的。不同的是,兩者的平臺不一樣, Monaco Editor
基于瀏覽器,而 VSCode
基于 electron
,所以功能上 VSCode
更加健全,性能比較強大。
用法
安裝
npm install monaco-editor --save
使用
<div id="monaco" class="monaco-editor"></div>
import * as monaco from 'monaco-editor'; this.fileEditor = this.monaco.editor.create(document.getElementById('monaco'), { value: null, language: 'sql' // 這里以sql為例 }) this.fileEditor.dispose(); // 使用完后銷毀
這里引入 monaco
要注意,在 react
中以下面方式引入:
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
實現自定義提示功能
查看了資料后,發現在 monaco
中有提供一個提示功能的方法 registerCompletionItemProvider
,具體實現如下:
this.monaco.languages.registerCompletionItemProvider('sql', { // 這里以sql語言為例 provideCompletionItems () { return [{ label: '${_DB', // 顯示的提示內容 kind: this.monaco.languages.CompletionItemKind['Function'], // 用來顯示提示內容后的不同的圖標 insertText: '{_DB', // 選擇后粘貼到編輯器中的文字 detail: '' // 提示內容后的說明 }]; }, triggerCharacters: ['$'] // 觸發提示的字符,可以寫多個 });
以上的用法,我試了一下之后發現,雖然 triggerCharacters
的值是數組,可以有多個,但是里面的字符串只能識別一個字符。一開始的需求是輸入 ${_
之后提示 ${_DB
,但是由于不能識別多個字符,只能做到出現 $
就提示。
還有一個問題就是 registerCompletionItemProvider
的第一個參數只能是字符串,如果有多種語言只能疊加重復寫,恰巧我的需求是有多種語言,所以只能如下解決,也就是每種語言都寫了一遍:
['json', 'yaml', 'php', 'go', 'sql', 'java', 'markdown', 'plaintext'].map(item => { this.monaco.languages.registerCompletionItemProvider(item, { provideCompletionItems () { return [{ label: '${_DB', kind: this.monaco.languages.CompletionItemKind['Function'], insertText: '{_DB', detail: '' }]; }, triggerCharacters: ['$'] }); });
需求是 ${_DB:key:value
,也就是說在輸入 ${_DB
后,再輸入一個 :
提示出 key
,在 key
之后輸入 :
提示 value
。
這里又碰到一個問題,需要知道當前輸入的內容來判斷是 $
還是 :
,而且后面兩個觸發提示的符號同是 :
,無法區分,只能通過識別 :
的位置來判斷是提示 key
還是 value
,所以還要知道當前輸入的 :
之前的內容。
那么只有在 provideCompletionItems
這一步判斷,但是查遍了資料沒有發現這樣的參數, provideCompletionItems
只有 model
、 position
、 token
這幾個參數,后來發現 model
中的 getLineContent
方法可以獲取指定行的所有內容,而 position
可以獲取當前輸入行的行數和列數,于是就有了以下解決方法:
this.monaco.languages.registerCompletionItemProvider(item, { provideCompletionItems (model, position) { // 獲取當前行數 const line = position.lineNumber // 獲取當前列數 const column = position.column // 獲取當前輸入行的所有內容 const content = model.getLineContent(line) // 通過下標來獲取當前光標后一個內容,即為剛輸入的內容 const sym = content[column - 2] if (sym === '$') { return [{ label: '${_DB', kind: this.monaco.languages.CompletionItemKind['Function'], insertText: '{_DB', detail: '' }]; } return [{ label: ':abb', kind: this.monaco.languages.CompletionItemKind['Function'], insertText: 'abb', detail: '' }, { label: ':bc', kind: this.monaco.languages.CompletionItemKind['Function'], insertText: 'bc', detail: '' }]; }, triggerCharacters: ['$', ':'] });
能獲取光標后的第一個內容,后面的內容就都能獲取啦,如果識別到前面的內容是 ${_DB
就提示 key
,否則提示 value
。
最后總結下來就是一定要多看文檔,勤于測試就能解決問題啦~
總結
以上所述是小編給大家介紹的vue中實現Monaco Editor自定義提示功能 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。