微软之前有个项目叫做Monaco Workbench,后来这个项目变成了VSCode,而Monaco Editor(就是从这个项目中成长出来的一个web编辑器,他们很大一部分的代码(monaco-editor-core)都是共用的,所以monaco和VSCode在编辑代码,交互以及UI上几乎是一摸一样的。
VS Code(基于electron) 包含了文件管理、版本控制、插件等功能,是一款桌面软件。
Monaco Editor (基于浏览器)可以看作是一个编辑器控件,只提供了基础的编辑器与语言相关的接口,可以被用于任何基于 Web 技术构建的项目中(不支持移动浏览器/移动 Web 框架)。
Monaco Editor 的核心功能与组件和 VS Code 基本一致,它们基本上都包含下图中这些小部件。
行号
Overlay Widget(覆盖窗口部件),可以渲染任意的内容小部件,能选择放置在顶部、底部或编辑器中间
ViewLine,每一行都表示一个 ViewLine
Decorations 装饰块,可以指定某个位置的代码块以何种样式呈现,例如修改其背景色、前景色等
Content Widget(内容部件),与 Overlay Widget 类似,但可以基于行、列指定其位置。
View Zone(查看区域), 与 Overlay、Content Widget 不同,它可以插入到特定的行之间将其撑开.
除了这些标配的部件之外,Monaco 还支持通过 Decorations API 来添加更多的装饰,例如版本控制中为修改过的行号添加一个色块,又或者在调试状态下显示断点信息等。
基本语法着色,多光标(ctr +shift + alt)
列框选择(shift + alt)
高级查找和替换(ctr + f),
格式化(shift + alt + F),
代码导航: 转到定义(ctr),类型定义, 查看引用等。
智能感知: 代码提示,补全, 验证功能
diff Editor: 差异编辑器
内置语言:javascript, css , dart, less, markdown, typescript, mysql, objective-c, python, scheme, shell,sql,vb, xml,json,等
自定义:
Monaco 本身只是一个文本编辑器,对于不同编程语言的基础支持(即高亮)则需要通过注册语言规则的方式来实现,Monaco 默认使用了名为 Monarch 的高亮系统(而 VS Code 使用的则是 Textmate )(支持设置与vs code 一致的高亮方案, 参考 monaco-editor-textmate)
Monarch 规定了语言需要包含的关键字、类型、操作符,以及 Tokenizer。Tokenizer 是一组正则表达式,表示以何种规则来识别这些关键字以及括号、注释块,Monarch 将会依照正则表达式的配置来匹配每个 Token,并为之渲染对应的主题色。
npm install monaco-editor
// 按需引入
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution'; // 引入javascript 语言
import 'monaco-editor/esm/vs/editor/contrib/find/browser/findController' // 搜索控件
// 全量引入
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api' // vue2 项目中
import * as monaco from 'monaco-editor' // vue3 项目中
let options: monaco.editor.IStandaloneEditorConstructionOptions = {
value: '', // 初始显示文字
language: 'typescript', // 语言支持
theme: 'vs', // 主题色官方自带: vs, hc-black , vs-dark
automaticLayout: true, // 自适应布局 默认true
renderLineHighlight: 'all', // 行亮方式 默认all
selectOnLineNumbers: true, // 显示行号 默认true
minimap: {
enabled: true,
},
readOnly: false, // 只读
fontSize: 16, // 字体大小
scrollBeyondLastLine: false, // 取消代码后面一大段空白
overviewRulerBorder: false, // 不要滚动条的边框}
}
monaco.editor.create(cusEditor.value, options)
Monaco的实现采用worker的方式,因为语法解析需要耗费大量时间,所以用worker来异步处理返回结果比较高效。
什么是web worker?web worker 详解
web worker是h5的一个新特性
,是为了解决js(js是单线程的)在处理一些耗时任务时阻塞页面的渲染交互导致用户体验不好的问题,它的作用就是给JS创造多线程运行环境,允许主线程创建worker线程,分配任务给后者,主线程运行的同时worker线程也在运行,相互不干扰,在worker线程运行结束后把结果返回给主线程。这样主线程就会变得轻松,不会被阻塞或拖慢。不过因为worker一旦新建,就会一直运行,不会被主线程的活动打断,这样有利于随时响应主线程的通信,但是也会造成资源的浪费,所以不应过度使用,用完注意关闭。
webpack项目配置
借助monaco-editor-webpack-plugin插件,它会帮我们做这么⼏件事
1. ⾃动注⼊getWorkerUrl全局变量
2. 处理worker的编译配置
3. ⾃动引⼊控件和语⾔包
安装依赖
npm install monaco-editor-webpack-plugin -S
webpack配置
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports=function(){
return {
...
plugins:[
// 具体引入哪些语言和控件配置(未配置默认引入全部)
new MonacoWebpackPlugin({
languages:["javascript","css","html","json"],
features:["coreCommands","find"]
})
]
...
}
}
vite项目配置 参考 vite解决Monaco 引入问题
import * as monaco from 'monaco-editor';
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
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';
// @ts-ignore: worker 导入方式可以参考vite官网 https://cn.vitejs.dev/guide/features.html#web-workers
self.MonacoEnvironment = { // 提供一个定义worker路径的全局变量
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都会去加载他。
}
};
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);