1. 安装

"monaco-editor": "^0.34.0",这个是 package.json 中的版本

  1. npm install monaco-editor

2. 在 vite.config.js 中配置

  1. optimizeDeps: {
  2. include: [
  3. `monaco-editor/esm/vs/language/json/json.worker`,
  4. `monaco-editor/esm/vs/language/css/css.worker`,
  5. `monaco-editor/esm/vs/language/html/html.worker`,
  6. `monaco-editor/esm/vs/language/typescript/ts.worker`,
  7. `monaco-editor/esm/vs/editor/editor.worker`
  8. ],
  9. },

3. 组件封装与使用

  1. monacoEditor.vue 组件
  1. <template>
  2. <div ref="codeEditBox" class="codeEditBox"></div>
  3. </template>
  4. <script lang="ts">
  5. import { defineComponent, onBeforeUnmount, onMounted, ref, watch } from 'vue'
  6. import { editorProps } from './monacoEditorType'
  7. import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
  8. import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
  9. import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
  10. import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
  11. import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
  12. import * as monaco from 'monaco-editor'
  13. export default defineComponent({
  14. name: 'monacoEditor',
  15. props: editorProps,
  16. emits: ['update:modelValue', 'change', 'editor-mounted'],
  17. setup(props, { emit }) {
  18. self.MonacoEnvironment = {
  19. getWorker(_: string, label: string) {
  20. if (label === 'json') {
  21. return new jsonWorker()
  22. }
  23. if (['css', 'scss', 'less'].includes(label)) {
  24. return new cssWorker()
  25. }
  26. if (['html', 'handlebars', 'razor'].includes(label)) {
  27. return new htmlWorker()
  28. }
  29. if (['typescript', 'javascript'].includes(label)) {
  30. return new tsWorker()
  31. }
  32. return new EditorWorker()
  33. },
  34. }
  35. let editor: monaco.editor.IStandaloneCodeEditor
  36. const codeEditBox = ref()
  37. const init = () => {
  38. monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
  39. noSemanticValidation: true,
  40. noSyntaxValidation: false,
  41. })
  42. monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
  43. target: monaco.languages.typescript.ScriptTarget.ES2020,
  44. allowNonTsExtensions: true,
  45. })
  46. editor = monaco.editor.create(codeEditBox.value, {
  47. value: props.modelValue,
  48. language: props.language,
  49. theme: props.theme,
  50. ...props.options,
  51. })
  52. editor.onDidChangeModelContent(() => {
  53. const value = editor.getValue()
  54. emit('update:modelValue', value)
  55. emit('change', value)
  56. })
  57. emit('editor-mounted', editor)
  58. }
  59. watch(
  60. () => props.modelValue,
  61. newValue => {
  62. if (editor) {
  63. const value = editor.getValue()
  64. if (newValue !== value) {
  65. editor.setValue(newValue)
  66. }
  67. }
  68. }
  69. )
  70. watch(
  71. () => props.options,
  72. newValue => {
  73. editor.updateOptions(newValue)
  74. },
  75. { deep: true }
  76. )
  77. watch(
  78. () => props.language,
  79. newValue => {
  80. monaco.editor.setModelLanguage(editor.getModel()!, newValue)
  81. }
  82. )
  83. onBeforeUnmount(() => {
  84. editor.dispose()
  85. })
  86. onMounted(() => {
  87. init()
  88. })
  89. return { codeEditBox }
  90. },
  91. })
  92. </script>
  93. <style lang="scss" scoped>
  94. .codeEditBox {
  95. width: v-bind(width);
  96. height: v-bind(height);
  97. }
  98. </style>
  1. monacoEditorType.ts 类型定义文件
  1. import { PropType } from 'vue'
  2. export type Theme = 'vs' | 'hc-black' | 'vs-dark'
  3. export type FoldingStrategy = 'auto' | 'indentation'
  4. export type RenderLineHighlight = 'all' | 'line' | 'none' | 'gutter'
  5. export interface Options {
  6. automaticLayout: boolean
  7. foldingStrategy: FoldingStrategy
  8. renderLineHighlight: RenderLineHighlight
  9. selectOnLineNumbers: boolean
  10. minimap: {
  11. enabled: boolean
  12. }
  13. readOnly: boolean
  14. fontSize: number
  15. scrollBeyondLastLine: boolean
  16. overviewRulerBorder: boolean
  17. }
  18. export const editorProps = {
  19. modelValue: {
  20. type: String as PropType<string>,
  21. default: null,
  22. },
  23. width: {
  24. type: [String, Number] as PropType<string | number>,
  25. default: '100%',
  26. },
  27. height: {
  28. type: [String, Number] as PropType<string | number>,
  29. default: '100%',
  30. },
  31. language: {
  32. type: String as PropType<string>,
  33. default: 'javascript',
  34. },
  35. theme: {
  36. type: String as PropType<Theme>,
  37. validator(value: string): boolean {
  38. return ['vs', 'hc-black', 'vs-dark'].includes(value)
  39. },
  40. default: 'vs-dark',
  41. },
  42. options: {
  43. type: Object as PropType<Options>,
  44. default: function () {
  45. return {
  46. automaticLayout: true,
  47. foldingStrategy: 'indentation',
  48. renderLineHighlight: 'all',
  49. selectOnLineNumbers: true,
  50. minimap: {
  51. enabled: true,
  52. },
  53. readOnly: false,
  54. fontSize: 16,
  55. scrollBeyondLastLine: false,
  56. overviewRulerBorder: false,
  57. }
  58. },
  59. },
  60. }
  1. 在父组件中使用
  1. <script lang="ts" setup>
  2. import * as monaco from 'monaco-editor'
  3. const value = ref('let a = 234')
  4. const language = ref('javascript')
  5. const editorMounted = (editor: monaco.editor.IStandaloneCodeEditor) => {
  6. console.log('editor实例加载完成', editor)
  7. }
  8. </script>
  9. <template>
  10. <div class="container">
  11. <monacoEditor
  12. v-model="value"
  13. :language="language"
  14. width="800px"
  15. height="500px"
  16. @editor-mounted="editorMounted"
  17. ></monacoEditor>
  18. </div>
  19. </template>

https://blog.csdn.net/weixin_44440116/article/details/126843676