使用场景:
数据编辑时需要支持sql语法高亮, 并且支持自定义代码提示补全。
monaco详细说明和使用可参考另一篇发文Monaco Editor (vite/webpack + ts + vue项目使用)
步骤一:安装依赖
npm i monaco-editor
步骤二:组件功能封装
- OPTIONS_BASE : 为基础配置,具体参数可参考官网
- worker: 解决vite引入代码高亮和错误提示
OPTIONS_BASE:
export const OPTIONS_BASE: monaco.editor.IStandaloneEditorConstructionOptions = { value: '', // 初始显示文字 lineNumbers: 'on', // 是否展示行号 'off' | 'on automaticLayout: false, // 自适应布局 默认true minimap: { enabled: false, }, tabSize: 2, fontSize: 16}
worker.ts
import * as monaco from 'monaco-editor';import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'self.MonacoEnvironment = { getWorker(_, label) { if (label === 'json') { return new jsonWorker() } if (label === 'css' || label === 'scss' || label === 'less') { return new cssWorker() } if (label === 'html' || label === 'handlebars' || label === 'razor') { return new htmlWorker() } if (label === 'typescript' || label === 'javascript') { return new tsWorker() } return new editorWorker() }}monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
步骤三:组件的使用
到此,就可以实现基础的编辑功能
*扩展
由于我项目中使用的时sql语法,并且还需要支持自定义代码补全, 接下来就以sql语言为例:
步骤一:自定义补全语法方法封装
import * as monaco from 'monaco-editor';export const registerProvider = (language: string, constValues: string[]) => { const monacoProvider = monaco.languages.registerCompletionItemProvider(language, { provideCompletionItems: function (model, position) { // 获取当前行数 const line = position.lineNumber // 获取当前列数 const column = position.column // 获取当前输入行的所有内容 const content = model.getLineContent(line) // 通过下标来获取当前光标后一个内容,即为刚输入的内容 const sym = content[column - 2] const word = model.getWordUntilPosition(position) const range = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: word.startColumn, endColumn: word.endColumn, } let suggestions: any[] = [] if (sym === '$') { suggestions = constValues.map((e) => ({ label: e, kind: monaco.languages.CompletionItemKind.Keyword, insertText: '{' + e + '}', detail: '常量配置', })) //拦截到用户输入$,开始设置提示内容,同else中代码一致,自行拓展 } else if(language === 'sql'){ // 直接提示,以下为sql语句关键词提示 var sqlStr = ['SELECT', 'FROM', 'WHERE', 'AND', 'OR', 'LIMIT', 'ORDER BY', 'GROUP BY', 'LEFT', 'ON', 'if(){}', 'for(){}', 'size', 'get()', 'substring', 'return'] suggestions = sqlStr.map((e) => ({ label: e, // 显示的提示内容 kind: monaco.languages.CompletionItemKind['Function'], // 用来显示提示内容后的不同的图标 insertText: e, // 选择后粘贴到编辑器中的文字 detail: '', // 提示内容后的说明 range: range, })) } return { suggestions: suggestions, } }, triggerCharacters: ['$', ''], }) return monacoProvider}
步骤二: 组件中使用
import { registerProvider } from '@/components/monaco/registerCompletion'const registerPro = registerProvider('sql', props.constModelData)
效果展示:
sql关键字提示
常量提示:
问题:每打开一次编辑弹框, 常量的提示就多一条重复数据。如图:
原因: registerCompletionItemProvider多次注册。由于自定义补全注册的代码写在了编辑弹框中,所以每打开一次弹框就执行一次注册自定义补全的方法,。
解决方案一:将注册方法移动到最外层组件中可解决
但是 由于功能需求,常量的提示内容要根据每次打开的弹框数据改变, 所以注册方法必须写在内部,(编辑弹框打开后,需根据弹框绑定数据的id去请求常量接口, 然后注册)
解决方案:参考官方:https://github.com/microsoft/monaco-editor/issues/2084
解决方案二:dispose(), 页面卸载时,销毁之前注册的实例
const registerPro = registerProvider('sql', props.constModelData)onUnmounted(() => { registerPro && registerPro.dispose()})
来源地址:https://blog.csdn.net/yyXieDaiMa/article/details/130198033