当前位置:   article > 正文

monaco-editor+vue3+ts+vite实现前端代码编辑器(初版)_vite vue3 ts 整合 monaco-editor

vite vue3 ts 整合 monaco-editor

最新有个sql在线编辑的需求,网上一些资料比较琐碎,总结归纳一下,复制直接使用

Vue3组件:

<template>
  <div id="codeEditBox" :style="'height:' + height + 'px'"></div>
</template>

<script lang="ts" setup>
import * as monaco from "monaco-editor";
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";
import EditorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
import {language as sqlLanguage} from "monaco-editor/esm/vs/basic-languages/sql/sql.js";
import {watch, nextTick, ref, onBeforeUnmount, onMounted, reactive, inject, defineProps, defineEmits} from "vue";

interface EditProp {
  text: string;
  language: string;
  theme: string;
  readonly: boolean;
  fontSize: number;
  height: number;
}

const editProp: EditProp = {
  text: "",
  language: "sql",
  theme: "vs-dark",
  readonly: false,
  fontSize: 14,
  height: 400,
};
// const fatherProp = defineProps(['heights'])
// fatherProp?fatherProp.heights:editProp.height;

const props = defineProps({
  value: {
    type: String,
    default: ''
  },
  height: {
    type: Number,
    default: 400
  },
  language: {
    type: String,
    default: 'sql'
  },
  theme: {
    type: String,
    default: 'vs-dark'
  },
  readonly: {
    type: Boolean,
    default: false
  },
  fontSize: {
    type: Number,
    default: 14
  }
});
const emit = defineEmits(["update:value"]);
/**
 * VS Code 编辑器
 *
 * 通过 getEditorVal 函数向外传递编辑器即时内容
 * 通过 initValue 用于初始化编辑器内容。
 * 编辑器默认 sql 语言,支持的语言请参考 node_modules\monaco-editor\esm\vs\basic-languages 目录下~
 * 编辑器样式仅有   'vs', 'vs-dark', 'hc-black' 三种
 * editor.setValue(newValue)
 * editor.getValue()
 * editor.onDidChangeModelContent((val)=>{ // 监听值的变化  })
 * editor.getAction('editor.action.formatDocument').run()    // 格式化代码
 * editor.dispose()    // 销毁实例
 * editor.onDidChangeOptions  // 配置改变事件
 * editor.onDidChangeLanguage  // 语言改变事件
 * editor.setModelMarkers // 标记错误
 *  monaco.languages.registerCompletionItemProvider // 设置代码提示补全
 */
onBeforeUnmount(() => {
  // 摧毁方法
  editor.dispose();
});
self.MonacoEnvironment = {
  getWorker(_: string, label: string) {
    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 (["typescript", "javascript"].includes(label)) {
      return new tsWorker();
    }
    return new EditorWorker();
  },
};
let editor: monaco.editor.IStandaloneCodeEditor;
const editorInit = () => {
  nextTick(() => {
    monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
      noSemanticValidation: true,
      noSyntaxValidation: false,
    });
    monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
      target: monaco.languages.typescript.ScriptTarget.ES2016,
      allowNonTsExtensions: true,
    });

    if (!editor) {
      editor = monaco.editor.create(
          document.getElementById("codeEditBox") as HTMLElement,
          {
            value: props.value, // 编辑器初始显示文字
            language: props.language, // 语言支持自行查阅demo
            automaticLayout: true, // 自适应布局
            theme: props.theme, // 官方自带三种主题vs, hc-black, or vs-dark
            foldingStrategy: "indentation",
            renderLineHighlight: "all", // 行亮
            selectOnLineNumbers: true, // 显示行号
            minimap: { // 代码缩略图
              enabled: false,
            },
            readOnly: props.readonly, // 只读
            fontSize: props.fontSize, // 字体大小
            scrollBeyondLastLine: false, // 取消代码后面一大段空白
            overviewRulerBorder: false, // 不要滚动条的边
          }
      )
    } else {
      editor.setValue("");
      emit("update:value", "");
    }
    // 监听值的变化
    editor.onDidChangeModelContent((val: any) => {
      // editProp.text = editor.getValue();
      emit("update:value", editor.getValue());
    });
    AutoCompletion();
    // codeErrorMarkers();
  });
};
editorInit();
// @ts-ignore
const changeLanguage = () => {
  monaco.editor.setModelLanguage(editor.getModel(), editProp.language);
};

const codeErrorMarkers = () => {
  monaco.editor.setModelMarkers(editor.getModel(), "json", [
    {
      startLineNumber: 2,
      endLineNumber: 2,
      startColumn: 1,
      endColumn: 1,
      severity: monaco.MarkerSeverity.Error,
      message: `语法错误`,
    },
  ]);
  console.log("editor", editor);
};

const AutoCompletion = () => {
  monaco.languages.registerCompletionItemProvider(props.language, {
    provideCompletionItems: () => {
      let suggestions = [];
      // 设置sql关键字
      sqlLanguage.keywords.forEach((item) => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Keyword,
          insertText: item,
        });
      });
      // 设置自定义关键字
      const customKeywords = ['nihao','id','customID','你好','FROM_UNIXTIME'];
      customKeywords.forEach((item) => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Keyword,
          insertText: item,
        });
      });
      // 设置sql操作
      sqlLanguage.operators.forEach((item) => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Operator,
          insertText: item,
        });
      });
      // 设置sql常用方法
      sqlLanguage.builtinFunctions.forEach((item) => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Function,
          insertText: item,
        });
      });
      // 设置sql执行变量
      sqlLanguage.builtinVariables.forEach((item) => {
        suggestions.push({
          label: item,
          kind: monaco.languages.CompletionItemKind.Variable,
          insertText: item,
        });
      });
      return {
        suggestions: suggestions,
      };
    },
  });
};
</script>

<style lang="less" scoped>
#codeEditBox {
  height: 400px;
}
</style>


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224

使用:

   <CodeEditor v-model:value="inquiry.sql_info" />
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/1000080
推荐阅读
相关标签
  

闽ICP备14008679号