开源可视化引擎 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的集成和使用。

相关推荐
涛思数据(TDengine)2 小时前
时序数据库 TDengine × SSRS:专为工业、能源场景打造的报表解决方案
大数据·数据库·物联网·时序数据库·tdengine
TESmart碲视4 小时前
USB一线连多屏?Display Link技术深度解析
stm32·单片机·嵌入式硬件·物联网·计算机外设·电脑·智能硬件
年纪轻轻就扛不住6 小时前
Express 入门指南(超详细教程)
前端·前端框架·node.js·express·js
杨进军10 小时前
实现 React 函数组件渲染
前端·react.js·前端框架
杨进军11 小时前
实现 React Fragment 节点渲染
前端·react.js·前端框架
杨进军11 小时前
实现 React 类组件渲染
前端·react.js·前端框架
杨进军11 小时前
实现 React 文本节点渲染
前端·react.js·前端框架
时序数据说11 小时前
时序数据库的存储之道:从数据特性看技术要点
大数据·数据库·物联网·开源·时序数据库·iotdb
杨进军12 小时前
简易实现 React 页面初次渲染
前端·react.js·前端框架
杨进军12 小时前
实现 React 多个原生标签子节点渲染
前端·react.js·前端框架