事件起因,因为之前一直用Node-Red为公司写一些报表统计类功能,写着写着就感觉有些别扭,Node-Red怎么对引入的js库没有智能提示呢?导致我每次用到对应的js插件时,总是要翻出它们的文档,进行一阵复制粘贴.本着浪费1秒也是罪恶,所以萌生了对monaco研究的想法
关于monaco的介绍和基础的使用,本文就不着重复述了,网上有大把的教程,写的都非常的详细
比如 基于monaco-editor写一个在线代码编辑器组件
开始本文的主题
这种使用方式,只要将库的声明文件配置进去后,即可全文使用这个库的代码感知
js// 设置诊断选项
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true, // 表示不进行语义验证
noSyntaxValidation: false, // 表示进行语法验证
});
// 设置编译器选项
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2015, // 制定ECMAScript的目标版本为ES2015
allowNonTsExtensions: true, // 表示允许非TS扩展
});
// 定义一个声明文件的源码
var libSource = [
"declare class Facts {",
" /**",
" * Returns the next fact",
" */",
" static next():string",
"}",
].join("\n");
var libUri = "ts:filename/facts.d.ts"; // 定义声明文件的URI
// 为javascript默认库添加额外的库
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);
// 使用Moncao API创建编辑器模型
monaco.editor.createModel(libSource, "typescript", monaco.Uri.parse(libUri));
var jsCode = [
'"use strict";',
"",
"class Chuck {",
" greet() {",
" return Facts.next();",
" }",
"}",
].join("\n");
monaco.editor.create(document.getElementById("container"), { // 在指定的HTML元素中创建一个Monaco编辑器
value: jsCode, // 编辑器的初始内容
language: "javascript", // 编辑器的语言设置为javascript
});
运行结果如下

可以看到 monaco已经可以感知到Facts类下的next()方法了,当你输入Facts时,next方法将会在列表里出现,想自行尝试的可以点击下列链接,可能需要魔法上网
说说优缺点
优点:无需import导入即可全文感知,适合像Node-Red 云代码里不需要进行库的导入操作的应用场景使用
缺点:不灵活,无法知道用户端到底需要什么js库,只能把一些常用库的声明文件无脑导进monaco中
js// 设置 TypeScript 的默认编译器选项
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2016, // 设置 ECMAScript 目标版本为 ES2016
allowNonTsExtensions: true, // 允许非 TypeScript 扩展
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs, // 设置模块解析策略为 Node.js 风格
module: monaco.languages.typescript.ModuleKind.CommonJS, // 设置模块系统为 CommonJS
noEmit: true, // 不输出编译后的文件
typeRoots: ["node_modules/@types"] // 设置类型声明文件的根路径
});
// 添加额外的库,这里添加了一个名为 Facts 的类
monaco.languages.typescript.typescriptDefaults.addExtraLib(
`export class Facts {
public next(): string;
}`,
// 指定库声明文件的路径
"node_modules/@types/facts.d.ts");
// 要插入到 Monaco 编辑器中的 JavaScript 代码
var jsCode = `import {Facts} from "facts";
console.log(new Facts().next());`
// 创建一个 Monaco 编辑器实例
monaco.editor.create(document.getElementById("container"), // 指定编辑器的容器元素
{
model: monaco.editor.createModel(jsCode, // 创建一个模型,其中包含要插入到编辑器中的代码
"typescript", // 指定语言为 TypeScript
new monaco.Uri("main.ts") // 创建一个新的 URI,用于表示模型的资源
)
});
与全局使用的区别就是需要指定monaco的配置 setCompilerOptions 中声明 typeRoots 属性,并且还需要在addExtraLib方法中指定添加的声明文件路径
可以看到,在monaco在线调试中

当我import {Facts} from "facts";导入库后,Facts的智能感知也跟着一起出现了