Monaco Editor 代码编辑器基本使用

1,551 阅读1分钟

在开发中具体运用场景如上图显示,在线编辑代码。

官方文档地址:microsoft.github.io/monaco-edit…

安装

npm install monaco-editor@0.30.1

vue3中具体使用

<div id="EditContainer" ref="EditContainer" style="height: 200px; width: 100%;"></div>

<script>
  import { getCurrentInstance, onMounted } from 'vue'
  import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js'
  import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution'
  import { parseSqlMetaData, createTips } from '@/views/utils/index.js'
  export default {
    name: "Demo",
    setup() {
       let monacoEditor = null;
       let completionItemProvider = null;
       const { proxy } = getCurrentInstance();

       const handleCodeComplete = (fillDocument, monaco) => {        // 创建代码提醒
        completionItemProvider = monaco.languages.registerCompletionItemProvider('sql', {
          provideCompletionItems: function(model, position) {
            // find out if we are completing a property in the 'dependencies' object.
            let suggestions = [];
            let word = model.getWordUntilPosition(position);
            suggestions = createTips(fillDocument, monaco, parseSqlMetaData(monacoEditor.getValue()));
            return {suggestions: suggestions};
          }
        });
      }

      onMounted(() => {
        // 获取自动补全内容
        proxy.$axios.get('/data').then(({ data }) => {
          let fillDocument = data.datas //拿到自定义的提示内容
          // 创建代码提醒
          handleCodeComplete(fillDocument, monaco)
        })
        monacoEditor = monaco.editor.create(proxy.$refs.EditContainer, {
          value: '',
          readOnly: false,
          language: 'sql',
          theme: 'vs-dark',
          selectOnLineNumbers: true,
          renderSideBySide: false,
        });
      })
      return {
            
      }
    }
  }

</script>

!!! 封装解析代码方法,如果需求没有这个要求的话,就不需要以下这堆方法

@/views/utils/index

export const createTips = (fillDocument, monaco, sqlMetaData) => {
  const fillSql = fillDocument.map(x => ({
    label: x.fillValue,
    kind: monaco.languages.CompletionItemKind[x.category || 'Text'],
    insertText: x.fillValue,
    insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
    detail: x.description
  }))
  const sqlMetaDataSql = []
  if (sqlMetaData.metaData && sqlMetaData.metaData.length) {
    sqlMetaData?.metaData?.forEach((item) => {
      sqlMetaDataSql.push({
        label: item.table,
        kind: monaco.languages.CompletionItemKind.Constant,
        insertText: item.table,
        insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
        detail: 'FlinkSQL Connector => ' + item.connector
      });
      item.columns.forEach((column) => {
        sqlMetaDataSql.push({
          label: column.name,
          kind: monaco.languages.CompletionItemKind.Field,
          insertText: column.name,
          insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
          detail: 'Column => ' + column.type + ' from ' + item.table
        });
      })
    })
  }

  const innerSql = [
    /**   * 内置函数   */
    {
      label: 'SUM(number)', //显示的提示名称
      kind: monaco.languages.CompletionItemKind.Function, // 展示的类型
      insertText: 'SUM(${1:})', //选择后粘贴到编辑器中的文字
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定参数的求和'
    },
    {
      label: 'SQRT(number)',
      kind: monaco.languages.CompletionItemKind.Function,
      insertText: 'SQRT(${1:})',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定参数的平方根'
    },
    {
      label: 'SIN(number)',
      kind: monaco.languages.CompletionItemKind.Function,
      insertText: 'SIN(${1:})',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定参数的正弦值'
    },
    {
      label: 'SINH(number)',
      kind: monaco.languages.CompletionItemKind.Function,
      insertText: 'SINH(${1:})',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定参数的双曲正弦值'
    },
    {
      label: 'SIGN(number)',
      kind: monaco.languages.CompletionItemKind.Function,
      insertText: 'SIGN(${1:})',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定参数的符合'
    },
    {
      label: 'SUBSTRING(string,integer1,integer2)',
      kind: monaco.languages.CompletionItemKind.Function,
      insertText: 'SUBSTRING(${1:})',
      insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
      detail: '返回指定字符串的子字符串'
    },
  ]
  return innerSql.concat(fillSql).concat(sqlMetaDataSql)
}

export const getStatements = (sql) => {
  return sql.split(';');
}

export const parseSqlMetaData = (sql) => {
  if(!sql||sql==='') {
    return false;
  }
  sql = sql.replaceAll('\r\n','').replaceAll(',',' ,').replaceAll(/\s+/g,' ');
  let statements = getStatements(sql);
  let metaDatas = [];
  for(let i in statements) {
    if(!statements[i]||statements[i]==='') {
      continue;
    }
    if(!/create\s+table/i.test(statements[i])) {
      continue;
    }
    metaDatas.push(regMetaData(statements[i]));
  }
  return {
    statement: sql,
    metaData: metaDatas,
  }
}

常用方法

1、monacoEditor.getValue()

获取editor内容,返回字符串,保留了所有信息换行、缩进、注释等。

2、monacoEditor.setValue()

更改editor内容,在实际开发中可用来实现回显功能。

3、monacoEditor.getSelection()

获取被选中的editor内容

4、monacoEditor.addAction()

自定义右键菜单