编辑
2023-12-22
前端
00

事件起因,因为之前一直用Node-Red为公司写一些报表统计类功能,写着写着就感觉有些别扭,Node-Red怎么对引入的js库没有智能提示呢?导致我每次用到对应的js插件时,总是要翻出它们的文档,进行一阵复制粘贴.本着浪费1秒也是罪恶,所以萌生了对monaco研究的想法

关于monaco的介绍和基础的使用,本文就不着重复述了,网上有大把的教程,写的都非常的详细

比如 基于monaco-editor写一个在线代码编辑器组件

开始本文的主题

1. 全局使用

这种使用方式,只要将库的声明文件配置进去后,即可全文使用这个库的代码感知

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 });

运行结果如下

image.png

可以看到 monaco已经可以感知到Facts类下的next()方法了,当你输入Facts时,next方法将会在列表里出现,想自行尝试的可以点击下列链接,可能需要魔法上网

monaco在线调试

说说优缺点

优点:无需import导入即可全文感知,适合像Node-Red 云代码里不需要进行库的导入操作的应用场景使用

缺点:不灵活,无法知道用户端到底需要什么js库,只能把一些常用库的声明文件无脑导进monaco中

esm方式使用

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在线调试

image.png

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