Monaco与VSCode
微软之前有个项目叫做Monaco Workbench,后来这个项目变成了VSCode,而Monaco Editor(下文简称monaco)就是从这个项目中成长出来的一个web编辑器,他们很大一部分的代码(monaco-editor-core)都是共用的,所以monaco和VSCode在编辑代码,交互以及UI上几乎是一摸一样的,有点不同的是,两者的平台不一样,monaco基于浏览器,而VSCode基于electron,所以功能上VSCode更加健全,并且性能比较强大。
Monaco 是一个用于浏览器中的编辑器,始于 2011 年 Erich Gamma 加入微软。后期主要使用在 Visual Studio Online, OneDrive 以及不少内部网站。最终使用 Electron 包装成为一个跨平台的编辑器,当然其实她还是在一个浏览器里。
官方demo示例:microsoft.github.io/monaco-edit…
如何使用:
这里只讲述使用monaco实现json编辑,如果想要实现代码编辑,可以参考该项目github.com/Tencent/tma…
- 安装
npm install *monaco*-*editor* --save
- main.ts 中提供一个定义worker路径的全局变量
import { createApp } from 'vue'
import * as monaco from 'monaco-editor';
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.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 JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
import './style.css'
import App from './App.vue'
// @ts-ignore
// vite/webpack搭建参考 https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md
globalThis.MonacoEnvironment = {
getWorker(_: any, label: string) {
if (label === 'json') {
return new JsonWorker();
}
if (label === 'css' || label === 'scss' || label === 'less') {
return new CssWorker();
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return new HtmlWorker();
}
if (label === 'typescript' || label === 'javascript') {
return new TsWorker();
}
return new EditorWorker();
},
};
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
createApp(App).mount('#app')
- vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
esbuildOptions: {
define: {
global: 'globalThis',
},
},
},
})
- 组件中使用
<template>
<div ref="jsonEditorRef" class="monaco-editor-content"></div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { throttle } from 'lodash-es'
import * as monaco from 'monaco-editor'
const jsonEditorRef = ref<HTMLDivElement>()
let jsonEditor: monaco.editor.IStandaloneCodeEditor | null = null
// 实现 monaco 自适应
const resizeObserver = new globalThis.ResizeObserver(
throttle((): void => {
jsonEditor?.layout()
}, 300)
)
const setEditorValue = (v: string | any) => {
const jsonValue = JSON.parse(JSON.stringify(v))
// json格式化
return JSON.stringify(jsonValue, null, 2)
}
const defaultValue = {
name: 'lucy',
age: 18,
}
const init = async () => {
if (!jsonEditorRef.value) return
let options = {
value: setEditorValue(defaultValue),
language: 'json',
theme: 'vs-dark',
tabSize: 2, // tab 缩进长度
minimap: {
enabled: false, // 不要小地图
},
}
jsonEditor = monaco.editor.create(jsonEditorRef.value, options)
resizeObserver.observe(jsonEditorRef.value)
}
onMounted(async () => {
init()
})
onUnmounted(() => {
resizeObserver.disconnect()
})
</script>
<style lang="less">
.monaco-editor-content {
width: 100vw;
height: 70vh;
}
</style>
- 搭建出的json编辑器
带有错误提示,并且由于我们直接对传入的数据进行了格式上的调整,所以展示出来不是一行
Tips:有一些细节方面需要注意:
- 由于使用vite,所以node版本至少为16
jsonEditor?.trigger('', 'editor.action.formatDocument', '');可以通过这种方式来实现对json数据的格式调整,但在实操中,通过jsonEditor?.setValue(JSON.parse(v))对json数据更新后,执行该操作,首次进入时,json仍旧以一行排列,第二次进入,才会格式调整,所以通过JSON.stringify(jsonValue, null, 2),在setValue之前,直接对json进行格式调整,然后塞入monaco- 为什么注册全局变量worker路径&self变量?juejin.cn/post/684490…