转自 : https://zhuanlan.zhihu.com/p/47746336

什么是Monaco Editor?

微软之前有个项目叫做Monaco Workbench,后来这个项目变成了VSCode,而Monaco Editor(下文简称monaco)就是从这个项目中成长出来的一个web编辑器,他们很大一部分的代码(monaco-editor-core)都是共用的,所以monaco和VSCode在编辑代码,交互以及UI上几乎是一摸一样的,有点不同的是,两者的平台不一样,monaco基于浏览器,而VSCode基于electron,所以功能上VSCode更加健全,并且性能比较强大。

开始使用

本文采用的是webpack编译,所以以下都是基于webpack来说明。

基本功能

首先,我们需要安装monaco

  1. npm install monaco-editor -S

然后在自己的文件中引入monaco,这里不需要全部引入,只需要引入自己需要使用的功能模块即可。
HTML

  1. <div id="monaco">
  2. </div>

JS

import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
const monacoInstance=monaco.editor.create(document.getElementById("monaco"),{
            value:`console.log("hello,world")`,
            language:"javascript"
})
monacoInstance.dispose();//使用完成销毁实例

闲谈Monaco Editor-基本使用 - 图1
我们设置了语言为javascript,界面是出来了,但是却发现没有语法高亮,输入命令发现其实根本没有javascript语言,只有一个最基础的plaintext。
闲谈Monaco Editor-基本使用 - 图2
所以我们还需要再定义一个javascript语言,但是定义一门语言并不是一件很容易的事情,幸好,monaco自身提供了许多种内置语言,我们只需要引入即可。

import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';

引入完成,再次查看界面,发现已经有了语法高亮。
闲谈Monaco Editor-基本使用 - 图3
这时,我们可以尝试像使用VSCode一样使用monaco,按下ctrl+f来执行文本查找,我们会发现出来的不是monaco的查找控件,而是浏览器的,因此我们需要引入查找控件。

import 'monaco-editor/esm/vs/editor/contrib/find/findController.js';

再次尝试查找,出来的已经是monaco的查找控件啦。
闲谈Monaco Editor-基本使用 - 图4
monaco还有许多这类控件,我们可以按需引入自己用到的。
不过有一个更加简便的方法,那就是直接引入main文件来代替api文件。

import * as monaco from 'monaco-editor/esm/vs/editor/editor.main.js';

点开文件,我们可以看到
editor.main.js

import '../language/typescript/monaco.contribution';
import '../language/css/monaco.contribution';
import '../language/json/monaco.contribution';
import '../language/html/monaco.contribution';
import '../basic-languages/monaco.contribution';
export * from './edcore.main';

采用这种方式引入的话,会自动带上所有的内置语言和控件,唯一的缺点就是包的体积过大

目前为止,我们已经实现了一个可以输入,高亮,查找的web编辑器,但是,和VSCode比较起来,还少了许多重要的功能,例如代码补全,错误提示以及快捷命令功能等。

增加代码提示

export default function (monaco) {
  // 创建代码提醒
  monaco.languages.registerCompletionItemProvider('xxx_name', {
    provideCompletionItems: function (model, position) {
      // find out if we are completing a property in the 'dependencies' object.
      var textUntilPosition = model.getValueInRange({
        startLineNumber: 1,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column
      });
      var suggestions = [];
      var word = model.getWordUntilPosition(position);
      var range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn
      };

      // console.log(textUntilPosition, range, word); 

      if (textUntilPosition.charAt(textUntilPosition.length - 2) == '.') {
        suggestions = [{
          label: "lenth",
          insertText: "length"
        }];
      }

      return { suggestions: suggestions };
    }
  });
}

**

结尾

本文重点在于介绍monaco的基本设计和使用,代码细节部分不是很详细,如果有疑问,可以翻阅monaco的官方文档。谢谢~