Vue3 中集成 Monaco Editor

官网: 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 的文档不是特别直观, 所以通过分析 "控制是否显示缩略图" 属性的来探索一下遇到其它问题的学习路径。

  1. 通过文档 microsoft.github.io/monaco-edit... 找到响应的属性
  2. 查看对应属性的描述 Interface IEditorMinimapOptions 或者通过在编辑器中跳转到属性的实现文档ts
  3. 分析各个属性

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,   //代码提示延时

查询 options 的 地址

microsoft.github.io/monaco-edit... 很多很全

相关推荐
__sgf__13 小时前
ES8(ES2017)新特性
前端·javascript
__sgf__13 小时前
ES9(ES2018)新特性
前端·javascript
送鱼的老默13 小时前
学习笔记--vue3 watchEffect监听的各种姿势用法和总结
前端·vue.js
你挚爱的强哥13 小时前
解决:动态文本和背景色一致导致文字看不清楚,用js获取背景图片主色调,并获取对比度最大的hex色值给文字
前端·javascript·github
英俊潇洒美少年13 小时前
js 同步异步,宏任务微任务的关系
开发语言·javascript·ecmascript
用户693717500138413 小时前
Android 手机终于能当电脑用了
android·前端
wooyoo13 小时前
花了一周 vibe 了一个 OpenClaw 的 Agent 市场,聊聊过程中踩的坑
前端·后端·agent
angerdream13 小时前
最新版vue3+TypeScript开发入门到实战教程之路由详解
前端·javascript·vue.js
送鱼的老默13 小时前
学习笔记--vue3 watch监听的各种姿势用法和总结
前端·vue.js
猪八宅百炼成仙14 小时前
解决 el-date-picker type:daterange 在 layout 布局中的宽度问题
前端·element