开源可视化引擎 Meta2d.js 实战 - 解析自定义格式数据1 - 集成monaco编辑器

在开发一个在页面上提供输入并保存js代码的编辑器功能时,考查了多个在线编辑器均不满意。因为在考察时,会不由自主的将这些编辑器和VSCode进行对比。了解到monaco编辑器其实是VSCode的网页版本时,马上决定就是它了。

先看看集成后的效果:

官网的文档api太多,短时间是很难了解到一个大概。又搜看了多篇 monaco 的安装和使用文章,居然没有一篇能够完整在本地正常运行的。无奈只能多次尝试,现在把集成要点说明如下,希望可以帮助需要的同学少走点弯路。

一、monaco 安装

本地环境: mbp m1 macos14 + vscode1.84.2 + npm9.5.1 + node18.16 + vue3.3.8

csharp 复制代码
yarn add monaco-editor

或者

npm install monaco-editor

二、monaco 配置

我们只需要做到一点即可:在全局对象 Window 中定义一个 monaco 运行时所需要的一个属性 MonacoEnvironment 并定义 getWorker 方法,根据编辑器的用途,定义其内容,如下:

typescript 复制代码
import { boot } from 'quasar/wrappers';
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';

// more info on params: https://v2.quasar.dev/quasar-cli/boot-files
export default boot(async () => {
  self.MonacoEnvironment = {
    getWorker(_, label) {
      if (label === 'json') {
        return new jsonWorker();
      }
      if (['css', 'scss', 'less'].includes(label)) {
        return new cssWorker();
      }
      if (['html', 'handlebars', 'razor'].includes(label)) {
        return new htmlWorker();
      }
      if (['typescript', 'javascript', 'ts', 'js'].includes(label)) {
        return new tsWorker();
      }
      return new EditorWorker();
    },
  };
});

上面的代码是quasar框架中,在系统启动时执行这段代码的一个写法。 getWorker方法内部是根据不同的label的值,来调用不同的解析器。

typescript 复制代码
self.MonacoEnvironment

self就是代表Window对象。本质上其实就是定义了一个名为 MonacoEnvironment 的对象,在其中定义了getWorker方法。monaco编辑器在运行时,会去全局对象Window中寻找 MonacoEnvironment 对象,并调用 getWorker 方法来解析和处理编辑器内的代码。

三、使用

3.1 声明

在模板中,必须给定一个初始高度,比如 30vh。

vue 复制代码
模板中
<div ref="codeEditBox" :style="{ height: height }" />

script中
// div的引用
const codeEditBox = ref();
// 声明一个编辑器对象
let editor: monaco.editor.IStandaloneCodeEditor;

3.2 初始化

typescript 复制代码
interface IProps {
  modelValue?: string;
  language?: string;
  theme?: string;

  // 编辑器区域高度,不包括窗口的header、footer
  height?: string;
}

const props = withDefaults(defineProps<IProps>(), {
  modelValue: '',
  language: 'javascript',
  theme: 'vs-dark',
  height: '30vh',
});

function init(initValue = '') {
  visible.value = true;
  if (initValue !== '') {
    value.value = initValue;
  }

  console.debug('创建 monaco 编辑器');
  monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: false
  })
  monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
    target: monaco.languages.typescript.ScriptTarget.ES2020,
    allowNonTsExtensions: true
  })

  editor = monaco.editor.create(codeEditBox.value, {
    value: value.value,
    language: props.language,
    theme: props.theme,
    foldingStrategy: 'indentation',
    automaticLayout: true,
    contextmenu: true,
    minimap: {
      enabled: false,
    },
    scrollBeyondLastLine: false,
    overviewRulerBorder: false
  })

  // 监听值的变化
  editor.onDidChangeModelContent(() => {
    const value = editor.getValue() //给父组件实时返回最新文本
    emit('update:modelValue', value)
  })


  emit('editor-mounted', editor)
  visible.value = false;
}
  

相关api的详细说明,可以去官网查看。不过有一个功能点比较实用 - 格式化

当我们通过编辑器打开输入的代码后,会发现这些代码是在一行的,居然没有格式化输出!这对于天天使用vscode+prettier的我们来说,无疑有点抓狂。研究了官网api文档,编写一个功能函数:

typescript 复制代码
// 格式化代码,如果在init方法后调用,则需要增加100ms延时
function formatCode() {
  if (editor) {
    const range = editor.getModel()?.getFullModelRange();
    editor.getAction('editor.action.formatDocument')?.run(range);
    visible.value = false;
  }
}

至此,就完成了monaco的集成和使用。

相关推荐
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
笑非不退13 小时前
前端框架对比和选择
前端框架
老章学编程i1 天前
Vue工程化开发
开发语言·前端·javascript·vue.js·前端框架
神一样的老师1 天前
面向MQTT基础物联网网络的Age-of-Information感知的保留消息策略
网络·物联网
Tlog嵌入式1 天前
蓝桥杯【物联网】零基础到国奖之路:十六. 扩展模块之矩阵按键
arm开发·stm32·单片机·mcu·物联网·蓝桥杯·iot
秃头女孩y1 天前
React基础-快速梳理
前端·react.js·前端框架
码农超哥同学1 天前
Python知识点:如何使用Google Cloud IoT与Python进行边缘计算
python·物联网·面试·编程·边缘计算
Small-K1 天前
前端框架中@路径别名原理和配置
前端·webpack·typescript·前端框架·vite
qq_294481311 天前
nrf 24l01使用方法
stm32·嵌入式硬件·物联网
sophie旭1 天前
我要拿捏 react 系列二: React 架构设计
javascript·react.js·前端框架