官网: microsoft.github.io/monaco-edit...
文档地址: microsoft.github.io/monaco-edit...
npm 地址: www.npmjs.com/package/mon...
Vue3 中集成 Monaco Editor
安装
bash
npm i monaco-editor
创建一个简单的代码编辑器
本段介绍了如何在项目中引入 Monaco Editor 以及 如何创建一个简单的代码编辑器。
实现效果
实现代码
vue
<script setup>
import { ref, onMounted } from 'vue'
// 引入 Monaco Editor
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
// 引入自定义语言 Monarch
import customLangMonarch from '@/components/editor/custom-lang-monarch'
// 注册自定义语言
monaco.languages.register({ id: 'custom' })
// 设置 Monarch Tokens 提供者
monaco.languages.setMonarchTokensProvider('custom', customLangMonarch)
// 创建对编辑器的引用
const editor = ref()
// 在组件挂载后执行
onMounted(() => {
// 创建 Monaco Editor 实例
monaco.editor.create(editor.value, {
// 设置初始代码值
value: `// 在此处输入您的语言的源代码...
class MyClass {
@attribute
void main() {
Console.writeln( "Hello Monarch world\n");
}
}`,
// 设置语言为自定义语言
language: 'custom'
})
})
</script>
<template>
<div class="editor-container">
<!-- 将编辑器容器绑定到 ref -->
<div id="editor" ref="editor"></div>
</div>
</template>
<style scoped>
.editor-container {
width: 100%;
height: 100%;
padding: 15px;
background: #ffffff;
}
#editor {
width: 100%;
height: 100%;
}
</style>
Monaco Editor的自定义语言定义,使用了Monarch格式。它定义了关键字、类型关键字、运算符、符号等各种语法元素的词法分析规则。注释部分详细说明了各个规则的作用和匹配方式。
js
/**
* 自定义语言定义,参考自 https://microsoft.github.io/monaco-editor/monarch.html
* (采用 Monarch 格式)
*/
export default {
// 关键字
keywords: [
'abstract', 'continue', 'for', 'new', 'switch', 'assert', 'goto', 'do', 'if', 'private',
'this', 'break', 'protected', 'throw', 'else', 'public', 'enum', 'return', 'catch', 'try',
'interface', 'static', 'class', 'finally', 'const', 'super', 'while', 'true', 'false'
],
// 类型关键字
typeKeywords: ['boolean', 'double', 'byte', 'int', 'short', 'char', 'void', 'long', 'float'],
// 运算符
operators: [
'=', '>', '<', '!', '~', '?', ':', '==', '<=', '>=', '!=', '&&', '||', '++', '--', '+', '-',
'*', '/', '&', '|', '^', '%', '<<', '>>', '>>>', '+=', '-=', '*=', '/=', '&=', '|=', '^=',
'%=', '<<=', '>>=', '>>>='
],
// 符号
symbols: /[=><!~?:&|+\-*\/\^%]+/,
// 转义字符
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
// 主要的标记器定义
tokenizer: {
root: [
// 标识符和关键字
[
/[a-z_$][\w$]*/,
{
cases: {
'@typeKeywords': 'keyword',
'@keywords': 'keyword',
'@default': 'identifier'
}
}
],
[/[A-Z][\w\$]*/, 'type.identifier'], // 为了美观显示类名
// 空白字符
{ include: '@whitespace' },
// 分隔符和运算符
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[
/@symbols/,
{
cases: {
'@operators': 'operator',
'@default': ''
}
}
],
// @ 注解
[/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }],
// 数字
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
[/\d+/, 'number'],
// 分隔符:放在数字后面是因为 .\d 浮点数
[/[;,.]/, 'delimiter'],
// 字符串
[/"([^"\\]|\\.)*$/, 'string.invalid'], // 未终止的字符串
[/"/, { token: 'string.quote', bracket: '@open', next: '@string' }],
// 字符
[/'[^\\']'/, 'string'],
[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
[/'/, 'string.invalid']
],
comment: [
[/[^\/*]+/, 'comment'],
[/\/\*/, 'comment', '@push'], // 嵌套注释
['\\*/', 'comment', '@pop'],
[/[\/*]/, 'comment']
],
string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }]
],
whitespace: [
[/[ \t\r\n]+/, 'white'],
[/\/\*/, 'comment', '@comment'],
[/\/\/.*$/, 'comment']
]
}
}
Monaco Editor的API和基本用法
常见的 API
API / 基本用法 | 描述 |
---|---|
monaco.editor.create() |
创建一个新的编辑器实例 |
monaco.editor.setModel() |
设置编辑器的数据模型 |
monaco.editor.getModels() |
获取当前所有已创建的编辑器的数据模型 |
monaco.editor.IStandaloneCodeEditor |
表示一个独立的代码编辑器实例 |
monaco.editor.IModel |
表示编辑器的数据模型 |
monaco.editor.createModel() |
创建一个新的编辑器数据模型 |
editor.setValue(content) |
设置编辑器的文本内容 |
editor.getValue() |
获取编辑器的文本内容 |
editor.onDidChangeModelContent(callback) |
监听编辑器内容变化事件 |
editor.dispose() |
销毁编辑器实例 |
monaco.editor.defineTheme() |
定义编辑器主题 |
monaco.languages.register() |
注册新的语言 |
monaco.languages.setMonarchTokensProvider() |
设置 Monarch 语法解析器提供者 |
下面将常见的几个 API 列举一些使用实例。
基本用法
1. 创建编辑器实例:
通过 monaco.editor.create()
方法创建一个新的编辑器实例,并指定其容器和初始配置。
javascript
const editor = monaco.editor.create(document.getElementById('editor-container'), {
value: 'console.log("Hello, world!")',
language: 'javascript'
});
2. 设置编辑器内容:
使用 editor.setValue()
方法设置编辑器的文本内容。
javascript
editor.setValue('console.log("Hello, world!")');
3. 获取编辑器内容:
使用 editor.getValue()
方法获取编辑器的文本内容。
javascript
const content = editor.getValue();
4. 监听编辑器事件:
使用 editor.onDidChangeModelContent()
方法监听编辑器内容变化事件。
javascript
editor.onDidChangeModelContent(event => {
console.log('Editor content changed:', event);
console.log(editor.getValue()) // 获取更新后的内容
emits('change', editor.getValue()) // 将更新后的内容暴露出去
});
5. 销毁编辑器实例:
使用 editor.dispose()
方法销毁编辑器实例。
javascript
editor.dispose();
创建编辑器的Options
js
const editorRef =ref()
onMounted(()=>{
const editor = monaco.editor.create(editorRef.value, {
value:"", // 编辑器初始显示内容
language: "javascript", // 支持语言
theme:"vs-dark" // 主题
// .........
})
})
<div id="editor" ref="editorRef"></div>
控制是否显示缩略图
因为manaco editor 的文档不是特别直观, 所以通过分析 "控制是否显示缩略图" 属性的来探索一下遇到其它问题的学习路径。
- 通过文档 microsoft.github.io/monaco-edit... 找到响应的属性
- 查看对应属性的描述 Interface IEditorMinimapOptions 或者通过在编辑器中跳转到属性的实现文档ts
- 分析各个属性
minimap: IEditorMinimapOptions
js
export interface IEditorMinimapOptions {
/**
* 是否启用缩略图的渲染。
* 默认为 true。
*/
enabled?: boolean;
/**
* 控制缩略图的渲染。
*/
autohide?: boolean;
/**
* 控制缩略图在编辑器中的位置。
* 默认为 'right'。
*/
side?: 'right' | 'left';
/**
* 控制缩略图的渲染模式。
* 默认为 'actual'。
*/
size?: 'proportional' | 'fill' | 'fit';
/**
* 控制缩略图滑块的渲染。
* 默认为 'mouseover'。
*/
showSlider?: 'always' | 'mouseover';
/**
* 是否在行上渲染实际文本(而不是颜色块)。
* 默认为 true。
*/
renderCharacters?: boolean;
/**
* 限制缩略图的宽度,最多渲染一定数量的列。
* 默认为 120。
*/
maxColumn?: number;
/**
* 缩略图中字体的相对大小。默认为 1。
*/
scale?: number;
}
options列表
vbnet
value
language
theme
readOnly
selectOnLineNumbers: true,
roundedSelection: false,
readOnly: false, // 只读
writeOnly: false,
cursorStyle: 'line', //光标样式
automaticLayout: true, //自动布局
glyphMargin: true, //字形边缘
useTabStops: false,
fontSize: 18, //字体大小
autoIndent: true, //自动布局
//quickSuggestionsDelay: 500, //代码提示延时