monaco编辑器的集成和使用

monaco编辑器的集成和使用

集成Monaco编辑器

  1. 安装依赖
1 npm i monaco-editor
2 npm i monaco-editor-webpack-plugin
  1. 配置vue.config.js
1 const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
2 module.exports = {
3   configureWebpack: {
4       plugins: [
5           new MonacoWebpackPlugin()
6       ]
7   }
8 }
  1. 使用monaco:
    想要在自己项目中使用monaco编辑器的话需要引入,然后给它一个空内容的容器节点,然后在这个块中使用monaco.editor.create方法创建monaco-editor实例即可。
  • 常规使用monaco:

html:

1 <div id="container" style="height:100%;"></div>

js:

1 import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
2 
3 monaco.editor.create(document.getElementById("container"), {
4     value: "123"
5 });

注意:
create方法接收3个参数:

- 第一个参数是editor所处的容器,是必选参数,这个容器应当是一个空的节点,也就是说我们上面id为container的节点内部不要有其他dom节点,editor会撑满container容器。
- 第二个参数是可配置的字段,可选。
- 第三个参数是复写的方法,可选。
  • 将monaco封装成组件使用:
    创建文件my-monaco-editor.vue文件:
1 <!--
2 my-monaco-editor:
3 基于monaco-editor封装的vue组件,支持尺寸、配置的响应式
4 -->
5 
6 <template>
7   <div :style="{height, width}" class="my-monaco-editor"></div>
8 </template>
9 
10 <script>
11 import * as monaco from 'monaco-editor'
12 
13 export default {
14   props: {
15     options: {
16       type: Object,
17       default: () => {
18       }
19     },
20     height: {
21       type: String,
22       default: '300px'
23     },
24     width: {
25       type: String,
26       default: '100%'
27     },
28     code: {
29       type: String,
30       default: ''
31     }
32   },
33   data() {
34     return {
35       defaultOptions: {
36         value: this.code, // 编辑器的值
37         language: 'javascript', //语言
38         theme: 'vs-dark', // 编辑器主题:vs, hc-black, or vs-dark
39         autoIndent: true, // 自动缩进
40         readOnly: false, // 是否只读
41       }
42     }
43   },
44   computed: {
45     standaloneEditorConstructionOptions() {
46       return Object.assign(this.defaultOptions, this.options)
47     }
48   },
49   methods: {
50     createMonacoEditor() {
51       this.monacoEditor = monaco.editor.create(this.$el, this.standaloneEditorConstructionOptions)
52       this.monacoEditor.onDidChangeModelContent(event => {
53         this.$emit('update:code', this.monacoEditor.getValue())
54       })
55     },
56     reSize() {
57       this.$nextTick(() => {
58         this.monacoEditor.layout()
59       })
60     }
61   },
62   mounted() {
63     this.createMonacoEditor()
64   },
65   watch: {
66     height() {
67       this.reSize()
68     },
69     width() {
70       this.reSize()
71     },
72     options: {
73       handler() {
74         this.$nextTick(() => {
75           this.monacoEditor.updateOptions(this.standaloneEditorConstructionOptions)
76         })
77       },
78       deep: true
79     }
80   }
81 }
82 </script>
83 
84 <style scoped>
85 </style>

然后在父组件中使用引入这个monaco编辑器组件并使用即可:

1  import MyMonacoEditor from '@/components/my-monaco-editor'
2 
3 
4  ......//其他代码
5 
6 
7 <my-monaco-editor :code.sync="code" :height="height" :options="options" :width="width"></my-monaco-editor>
  1. monaco编辑器创建的时候有很多配置,例如主题、内容以什么语言识别、是否启用上下文菜单、是否仅读等。monaco编辑器的基础配置如下:
1    this.editor = monaco.editor.create(this.$refs.editor, {
2       acceptSuggestionOnCommitCharacter: true, // 接受关于提交字符的建议
3       acceptSuggestionOnEnter: 'on', // 接受输入建议 "on" | "off" | "smart" 
4       accessibilityPageSize: 10, // 辅助功能页面大小 Number 说明:控制编辑器中可由屏幕阅读器读出的行数。警告:这对大于默认值的数字具有性能含义。
5       accessibilitySupport: 'on', // 辅助功能支持 控制编辑器是否应在为屏幕阅读器优化的模式下运行。
6       autoClosingBrackets: 'always', // 是否自动添加结束括号(包括中括号) "always" | "languageDefined" | "beforeWhitespace" | "never"
7       autoClosingDelete: 'always', // 是否自动删除结束括号(包括中括号) "always" | "never" | "auto"
8       autoClosingOvertype: 'always', // 是否关闭改写 即使用insert模式时是覆盖后面的文字还是不覆盖后面的文字 "always" | "never" | "auto"
9       autoClosingQuotes: 'always', // 是否自动添加结束的单引号 双引号 "always" | "languageDefined" | "beforeWhitespace" | "never"
10       autoIndent: 'None', // 控制编辑器在用户键入、粘贴、移动或缩进行时是否应自动调整缩进
11       automaticLayout: true, // 自动布局
12       codeLens: false, // 是否显示codeLens 通过 CodeLens,你可以在专注于工作的同时了解代码所发生的情况 – 而无需离开编辑器。 可以查找代码引用、代码更改、关联的 Bug、工作项、代码评审和单元测试。
13       codeLensFontFamily: '', // codeLens的字体样式
14       codeLensFontSize: 14, // codeLens的字体大小
15       colorDecorators: false, // 呈现内联色彩装饰器和颜色选择器
16       comments: {
17         ignoreEmptyLines: true, // 插入行注释时忽略空行。默认为真。
18         insertSpace: true // 在行注释标记之后和块注释标记内插入一个空格。默认为真。
19       }, // 注释配置
20       contextmenu: true, // 启用上下文菜单
21       columnSelection: false, // 启用列编辑 按下shift键位然后按↑↓键位可以实现列选择 然后实现列编辑
22       autoSurround: 'never', // 是否应自动环绕选择
23       copyWithSyntaxHighlighting: true, // 是否应将语法突出显示复制到剪贴板中 即 当你复制到word中是否保持文字高亮颜色
24       cursorBlinking: 'Solid', // 光标动画样式
25       cursorSmoothCaretAnimation: true, // 是否启用光标平滑插入动画  当你在快速输入文字的时候 光标是直接平滑的移动还是直接"闪现"到当前文字所处位置
26       cursorStyle: 'UnderlineThin', // "Block"|"BlockOutline"|"Line"|"LineThin"|"Underline"|"UnderlineThin" 光标样式
27       cursorSurroundingLines: 0, // 光标环绕行数 当文字输入超过屏幕时 可以看见右侧滚动条中光标所处位置是在滚动条中间还是顶部还是底部 即光标环绕行数 环绕行数越大 光标在滚动条中位置越居中
28       cursorSurroundingLinesStyle: 'all', // "default" | "all" 光标环绕样式
29       cursorWidth: 2, // <=25 光标宽度
30       minimap: {
31         enabled: false // 是否启用预览图
32       }, // 预览图设置
33       folding: true, // 是否启用代码折叠
34       links: true, // 是否点击链接
35       overviewRulerBorder: false, // 是否应围绕概览标尺绘制边框
36       renderLineHighlight: 'gutter', // 当前行突出显示方式
37       roundedSelection: false, // 选区是否有圆角
38       scrollBeyondLastLine: false, // 设置编辑器是否可以滚动到最后一行之后
39       readOnly: false, // 是否为只读模式
40       theme: 'vs'// vs, hc-black, or vs-dark
41     })

语言的配置:

1  language: {
2   'apex': 'apex',
3   'azcli': 'azcli',
4   'bat': 'bat',
5   'c': 'c',
6   'clojure': 'clojure',
7   'coffeescript': 'coffeescript',
8   'cpp': 'cpp',
9   'csharp': 'csharp',
10   'csp': 'csp',
11   'css': 'css',
12   'dockerfile': 'dockerfile',
13   'fsharp': 'fsharp',
14   'go': 'go',
15   'graphql': 'graphql',
16   'handlebars': 'handlebars',
17   'html': 'html',
18   'ini': 'ini',
19   'java': 'java',
20   'javascript': 'javascript',
21   'json': 'json',
22   'kotlin': 'kotlin',
23   'less': 'less',
24   'lua': 'lua',
25   'markdown': 'markdown',
26   'msdax': 'msdax',
27   'mysql': 'mysql',
28   'objective-c': 'objective-c',
29   'pascal': 'pascal',
30   'perl': 'perl',
31   'pgsql': 'pgsql',
32   'php': 'php',
33   'plaintext': 'plaintext',
34   'postiats': 'postiats',
35   'powerquery': 'powerquery',
36   'powershell': 'powershell',
37   'pug': 'pug',
38   'python': 'python',
39   'r': 'r',
40   'razor': 'razor',
41   'redis': 'redis',
42   'redshift': 'redshift',
43   'ruby': 'ruby',
44   'rust': 'rust',
45   'sb': 'sb',
46   'scheme': 'scheme',
47   'scss': 'scss',
48   'shell': 'shell',
49   'sol': 'sol',
50   'sql': 'sql',
51   'st': 'st',
52   'swift': 'swift',
53   'tcl': 'tcl',
54   'typescript': 'typescript',
55   'vb': 'vb',
56   'xml': 'xml',
57   'yaml': 'yaml'
58 },

取消自动诊断功能的配置(就是取消自动出现红色波浪线下划线):

1       // 设置诊断选项,去除自带的红色波浪线
2       monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
3         noSemanticValidation: true, // 禁用语义验证
4         noSyntaxValidation: true, // 禁用语法验证
5       });
6       // 配置 JavaScript 的诊断选项
7       monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
8         noSemanticValidation: true,
9         noSyntaxValidation: true,
10       });

monaco编辑器的api使用

这里着重讲一下我在制作项目时使用到的api(monaco编辑器有众多api,下文中未讲到的想要了解的可以点击网址查看:monacoa编辑器API

  1. 获取编辑器文本模型getModel
  • 语法: getModel(): ITextModel
  • 返回值:一个ITextModel对象,表示编辑器的文本模型。
  • 示例:在grammily like项目中,需要对编辑器内容进行操作(例如获取相应文本的位置,和使用替换文本的api都需要提前获取到文本模型),故需要提前获取到文本模型:
1  const model = this.monacoEditor.getModel();
  1. 获取指定位置的偏移量getPositionAt
  • 语法:getPositionAt(offset: number): IPosition
  • 返回值: IPosition
  • 描述: 用于获取给定偏移量的位置。 offset 参数是一个 number 类型,表示要获取位置的偏移量。
  • 示例:我做的项目中需要对编辑器中的对应位置的错词进行操作,故需要获取到它们的位置,此时,使用此api进行偏移量位置获取:
1       const startPos = model.getPositionAt(wordItem.refPos);
2       const endPos = model.getPositionAt(
3         wordItem.refPos + wordItem.wordText.length
4       );
  1. 装饰器deltaDecorations
    语法结构:
1 deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[]

参数:

  • oldDecorations: string[]:表示老的装饰器,
  • newDecorations:表示新的装饰器。
  • 整个语法的意义就是使用新的装饰器去替换掉旧的装饰器。

示例:使用装饰器来给文本的对应内容增加不同的类名。

1       const decorationOptions = this.wordCompareResult.map((item, index) => {
2         const startPos = model.getPositionAt(item.refPos);
3         const endPos = model.getPositionAt(item.refPos + item.wordText.length);
4         return {
5           range: new monaco.Range(
6             startPos.lineNumber,
7             startPos.column,
8             endPos.lineNumber,
9             endPos.column
10           ),
11           options: {
12             inlineClassName: `remark${index}`,
13           },
14         };
15       });
16 
17       this.decorations = this.monacoEditor.deltaDecorations(
18         this.decorations,
19         decorationOptions
20       );
  • range:是monaco.Range的一个实例,用来定义装饰器装饰的范围,接受四个参数:
    -startLineNumber: 装饰开始的行号。
    -startColumn: 装饰开始的列号。
    -endLineNumber: 装饰结束的行号。
    -endColumn: 装饰结束的列号。
  • options:用来指定怎么装饰在"range"范围内的内容,上面示例是给范围内的内容增加一个类名。
  • 最后使用下面代码应用新的装饰器即可:
this.monacoEditor.deltaDecorations(this.decorations,decorationOptions);
  1. 编辑文本的api:model.applyEdits
    其中,model为当前编辑器的文本模型。
  • 语法: applyEdits(operations: IIdentifiedSingleEditOperation[]): void
  • 描述:用于将一组文本编辑应用于模型。该方法接受一个编辑操作数组和一个选项对象作为参数,并返回一个IMarkerData数组,其中包含所有已插入的标记的位置和数据。
    示例:对相应位置的文本进行文本替换。
1     replaceTextAndShow(cardId) {
2       const model = this.monacoEditor.getModel();
3       if (!model) return;
4 
5       const wordItem = this.wordCompareResult[cardId];
6       if (!wordItem) return;
7 
8       const startPos = model.getPositionAt(wordItem.refPos);
9       const endPos = model.getPositionAt(
10         wordItem.refPos + wordItem.wordText.length
11       );
12       const newWordText = wordItem.suggestText;
13 
14       model.applyEdits([
15         {
16           range: new monaco.Range(
17             startPos.lineNumber,
18             startPos.column,
19             endPos.lineNumber,
20             endPos.column
21           ),
22           text: newWordText,
23         },
24       ]);
25 
26       this.applyHighlight();
27     },
  • 先使用getModel获取到当前编辑器的文本模型
  • 使用range定义需要编辑的文本的范围
  • 使用model.applyEdits指定范围和新文本进行替换
  1. 获取文本内容的api getValue
  • 语法: getValue(): string
  • 参数: -
  • 返回值: string
  • 描述: 获取编辑器的文本内容
  • 示例:
1 const editor = monaco.editor.create(document.getElementById('container'), {
2     value: 'Hello, world!',
3     language: 'plaintext'
4 });
5 
6 const value = editor.getValue();
7 console.log(value);
  1. 获取光标位置的api onDidChangeCursorPosition
  • 参数: monaco.editor.ICursorPositionChangedEvent
  • 描述: 在光标位置发生变化时触发。可以通过监听这个事件来实现自定义的光标位置处理逻辑。
  • 示例:光标位置变化时,即可在控制台打印出光标的位置(包括行号,列号)。
1 const editor = monaco.editor.create(document.getElementById('container'), {
2     value: 'Hello, world!',
3     language: 'plaintext'
4 });
5 
6 editor.onDidChangeCursorPosition((e: monaco.editor.ICursorPositionChangedEvent) => {
7     console.log('Cursor position changed:', e.position);
8 });
  1. 监听鼠标点击事件的api onMouseDown
  • 参数: monaco.editor.IEditorMouseEvent
  • 描述: 在编辑器中按下鼠标按钮时触发。可以通过监听这个事件来实现自定义的鼠标按键处理逻辑。
  • 示例:下面代码实现的是,当在编辑器内点击鼠标时,在控制台打印相关信息。
1 const editor = monaco.editor.create(document.getElementById('container'), {
2     value: '',
3     language: 'plaintext'
4 });
5 
6 editor.onMouseDown((e: monaco.editor.IEditorMouseEvent) => {
7     console.log('Mouse down:', e.target.type);
8 });
  1. 更新编辑器配置api updateOptions
  • 语法: updateOptions(newOptions: IEditorOptions): void
  • 参数: newOptions
  • 返回值: -
  • 描述: 更新编辑器的配置
  • 示例:写一个按钮,点击以后控制编辑器的内容为只读还是可编辑态,这个按钮依靠此api实现,点击按钮以后调研以下函数,将编辑器配置中的readOnly设置为上一次的相反值,从而实现编辑器是否仅可读。
1     updateReadOnly(isReadOnly) {
2       this.monacoEditor.updateOptions({
3         readOnly: !isReadOnly,
4       });
5     },
  1. 设置编辑器文本内容的api setValue
  • 语法:setValue(value: string): void;
  • 参数:内容value
  • 返回值: -
  • 描述: 将整个编辑器中的文本内容替换为提供的字符串 value。这意味着当前模型中的所有文本将被新文本覆盖。
  • 示例:通过下面代码,整个编辑器内容会被替换成hello world。
1 // 获取编辑器模型
2 const model = monaco.editor.getModels();
3 
4 // 设置新的文本内容
5 model.setValue('hello world');
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值