ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

ng-zorro-antd Code Editor 组件全指南:在 Angular 中集成 monaco-editor 的加载模式、配置与实战

ng-zorro-antd Code Editor 组件全指南:在 Angular 中集成 monaco-editor 的加载模式、配置与实战 UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载导读nz-code-editor是 ng-zorro-antd 基于微软 monaco-editor 封装的开箱即用型 Angular 代码编辑器组件适用于在 Angular 应用中实现带语法高亮、智能提示与 diff 对比的在线编码能力。本文将以 组件官方文档 为主线完整讲解它的动态/静态两种加载方式、全部 API 参数、全局配置项并结合仓库源码code-editor.component.ts、code-editor.service.ts与官方 Demo 深入剖析其底层实现原理。读完本文你将能够独立完成 monaco-editor 的接入、按需加载配置、diff 模式、全控制模式以及主题切换等实战场景。注意该组件在文档中标记为experimental: trueAPI 在未来版本中可能调整接入前请关注版本变更说明。When To Use什么场景下使用当你的 Angular 项目中需要以组件化方式使用 monaco-editor 时即可使用nz-code-editor。它替你处理了 monaco 资源加载、编辑器实例创建、Angular 变更检测与 monaco 事件循环之间的协作、以及ngModel双向绑定等繁琐细节让你专注于业务代码本身。官方仓库中提供了 5 个可直接运行的示例components/code-editor/demo覆盖了基础用法、diff 对比、全控制模式、全局配置与进阶loading 与 toolbar场景下文将逐一展开。引入样式组件依赖自身的样式以及 spin 组件的样式在项目的全局样式入口引入import node_modules/ng-zorro-antd/code-editor/style/entry.less;从源码 style/entry.less 可以看到该入口会导入自身的index.less并级联引入../../spin/style/entry.less因为组件内部使用了nz-spin作为加载态所以这条 import 是完整自洽的无需额外手动引入 spin 样式。第一步安装 monaco-editornz-code-editor本身不内置 monaco-editor需要先在项目中显式安装npm install monaco-editor安装完成后根据你的资源部署方式选择「动态加载」或「静态加载」之一二者选其一不要同时配置。动态加载Dynamic Loading动态加载的含义是只有在真正使用编辑器的那一刻才从指定资源路径加载 monaco 的脚本。这是默认行为适合大多数常规应用。将 monaco 资源加入 angular.json由于运行时才加载需要把 monaco 的静态资源复制到你的应用资源目录中在angular.json的 assets 配置中加入如下条目assets: [ { glob: **/*, input: ./node_modules/monaco-editor/min/vs, output: /assets/vs/ } ],这样构建后 monaco 的vs目录会被整体拷贝到应用的/assets/vs/下组件默认会从这个相对地址加载资源。通过 CDN 部署资源配置 assetsRoot如果你的 monaco 资源部署在 CDN 上就不必修改angular.json而是要通过NzConfigService配置assetsRoot属性。例如资源放在https://mycdn.com/assets/vs则this.nzConfigService.set(codeEditor, { assetsRoot: https://mycdn.com/assets/vs });关于如何使用NzConfigService.set全局设置组件配置可参考 global-config 文档。底层实现动态加载是如何工作的从 code-editor.service.ts 的loadMonacoScript()方法可以看到完整链路拼接资源地址const vs assetsRoot ?${assetsRoot}/vs: assets/vs;即默认加载/assets/vs/loader.js动态创建script标签插入文档根元素注册load/error监听加载成功后调用window.require.config({ paths: { vs }, ...extraConfig })配置 AMD 路径通过require([vs/editor/editor.main], ...)拉取编辑器主模块随后触发onLoad()回调并完成loadingStatus状态流转unload - loading - LOADED。值得注意的工程细节loadScript的监听器在加载完成后会被主动removeEventListener并移除script节点code-editor.service.ts以避免闭包引用this造成 service 无法被垃圾回收。此外加载状态与loaded$ReplaySubject 被设计为模块级静态变量保证即使微前端应用被多次引导monaco 也只加载一次见 code-editor.service.ts 的注释说明。静态加载Static Loading为什么要静态加载monaco 的 AMD loader 会改写window[require]全局对象如果你的应用恰好也需要 AMD 加载器如 requireJS来加载其它模块二者会互相冲突。此时就需要把 monaco 直接打包进 bundle彻底绕开运行时 AMD 加载。三种静态加载的前提官方文档给出了三个步骤在全局配置中开启useStaticLoading在app.config.ts中通过NZ_CONFIG提供配置将codeEditor属性中的useStaticLoading设为true编写 webpack 配置新建webpack.partial.js配置 monaco-editor-webpack-loader微软官方插件 monaco-editor-webpack-plugin挂载自定义 webpack 配置使用自定义 webpack loader 工具如 ngx-build-plus加载上述 webpack 配置。// app.config.ts export const appConfig: ApplicationConfig { providers: [ { provide: NZ_CONFIG, useValue: { codeEditor: { useStaticLoading: true } } } ] };// webpack.partial.js const MonacoWebpackPlugin require(monaco-editor-webpack-plugin); module.exports { plugins: [new MonacoWebpackPlugin()] };重要提醒使用静态加载时不要再通过修改angular.json的方式把 monaco 资源复制进项目否则会出现重复加载。源码侧对静态加载的校验服务端渲染与静态加载是两个容易踩坑的点源码中给出了防御性提示。在 code-editor.service.ts 的requestToInit()中if (this.config.useStaticLoading typeof monaco undefined) { warn( You choose to use static loading but it seems that you forget to config webpack plugin correctly. Please refer to our official website for more details about static loading. ); } else { this.loadMonacoScript(); }即开启了静态加载但全局monaco变量不存在说明 webpack 插件未生效会发出告警日志反之则直接走loadMonacoScript()的动态路径。而在 code-editor.component.ts 的ngAfterViewInit()中组件会先判断platform.isBrowser服务端渲染环境直接跳过初始化避免 SSR 阶段操作 DOM。组件 APInz-code-editor输入 / 输出属性参数说明类型默认值[nzEditorMode]monaco 编辑器模式normal|diffnormal[nzLoading]是否显示加载中的 spinbooleanfalse[nzOriginalText]diff模式下左侧编辑器的内容booleanfalse[nzFullControl]启用全控制模式此时需手动管理TextModelbooleanfalse[nzEditorOption]编辑器配置参考 monaco 的IEditorConstructionOptionsIEditorConstructionOptions{}[nzToolkit]用于添加快捷操作的模板占位TemplateRefvoid-(nzEditorInitialized)编辑器初始化完成事件IStandaloneCodeEditor|IStandaloneDiffEditor-对应源码中的输入输出定义见 code-editor.component.ts其中nzLoading与nzFullControl通过booleanAttribute转换nzEditorOption使用 setter 将新值推入editorOption$流nzEditorInitialized以 EventEmitter 向外抛出编辑器实例。方法方法说明layout()强制 monaco 编辑器重新渲染自身基础用法normal 模式组件实现了ControlValueAccessorcode-editor.component.ts因此可以直接配合ngModel/ 响应式表单使用。以下是最简示例demo/basic.tsimport { Component } from angular/core; import { FormsModule } from angular/forms; import { NzCodeEditorModule } from ng-zorro-antd/code-editor; Component({ selector: app-code-editor-basic, imports: [FormsModule, NzCodeEditorModule], template: nz-code-editor classeditor [ngModel]code [nzEditorOption]{ language: typescript } / , styles: .editor { height: 200px; } }) export class AppCodeEditorBasicComponent { code import { NzCodeEditorModule } from ng-zorro-antd/code-editor Component({}) export class SomeComponent {}; }注意nz-code-editor需要一个明确的高度示例中通过 CSS 设置200px否则容器高度为 0 时编辑器无法正常显示。nzEditorOption中最常用的就是language当前示例为typescript。diff 模式设置nzEditorModediff并使用[nzOriginalText]传入左侧原版内容、[ngModel]绑定右侧修改版内容即可demo/diff.tsComponent({ selector: app-code-editor-diff, imports: [FormsModule, NzCodeEditorModule], template: nz-code-editor classeditor [nzOriginalText]originalCode nzEditorModediff [ngModel]code [nzEditorOption]{ language: typescript } / , styles: .editor { height: 200px; } }) export class AppCodeEditorDiffComponent { originalCode import { NzCodeEditorModule } from ng-zorro-antd/code-editor; Component({}) export class SomeComponent {}; code import { NzCodeEditorModule } from ng-zorro-antd/code-editor; Component({}) export class SomeComponent {}; }从源码 code-editor.component.ts 可以确认diff 模式会通过monaco.editor.createDiffEditor创建实例并用monaco.editor.createModel分别构建original与modified两个 TextModel。全控制模式full control设置[nzFullControl]true后组件不再替你管理内容你需要监听nzEditorInitialized事件拿到编辑器实例并手动创建 / 设置TextModeldemo/full-control.tsimport { Component } from angular/core; import type { editor } from monaco-editor; import { NzCodeEditorModule } from ng-zorro-antd/code-editor; declare const monaco: any; Component({ selector: app-code-editor-full-control, imports: [NzCodeEditorModule], template: nz-code-editor classeditor [nzFullControl]true (nzEditorInitialized)onEditorInit($event) / , styles: .editor { height: 200px; } }) export class AppCodeEditorFullControlComponent { editor?: editor.ICodeEditor | editor.IEditor; onEditorInit(e: editor.ICodeEditor | editor.IEditor): void { this.editor e; this.editor.setModel(monaco.editor.createModel(console.log(Hello ng-zorro-antd), typescript)); } }全控制模式的使用约束在源码中有明确体现setValue()中一旦检测到nzFullControl this.value会直接warn并返回code-editor.component.ts提示「全控制模式下不应设置值否则会造成数据流歧义」。对应这条行为的测试用例可在 code-editor.spec.ts 中看到。进阶示例loading 与 toolkit 工具栏nzLoading控制组件顶部的 spin 遮罩nzToolkit可以插入任意快捷操作模板。官方 demo/complex.ts 用它实现了「全屏切换」按钮Component({ selector: app-code-editor-complex, imports: [FormsModule, NzCodeEditorModule, NzIconModule, NzSwitchModule, NzTooltipModule], template: div Loading nz-switch [(ngModel)]loading / /div br / nz-code-editor classeditor [class.fullscreen]fullscreen() [ngModel]code [nzLoading]loading() [nzToolkit]toolkit [nzEditorOption]{ language: javascript } / ng-template #toolkit nz-icon [class.active]fullscreen() nz-tooltip nzTooltipTitleToggle Fullscreen [nzType]fullscreen() ? fullscreen-exit : fullscreen (click)toggleFullScreen() / /ng-template , styles: .editor { height: 200px; } .fullscreen { position: fixed; z-index: 999; height: 100vh; left: 0; top: 0; bottom: 0; right: 0; } }) export class AppCodeEditorComplexComponent { // ...toggleFullScreen() 中切换 body 滚动并调用 this.editorComponent?.layout() }组件模板code-editor.component.ts会分别渲染.ant-code-editor-loading遮罩与.ant-code-editor-toolkit工具栏插槽。全局配置CodeEditorConfig通过NzConfigService.set(codeEditor, ...)可以统一设置所有nz-code-editor实例的默认行为。常用场景是全局切换主题——官方 demo/config.ts 展示了通过开关在vs亮色与vs-dark暗色之间切换const defaultEditorOption this.nzConfigService.getConfigForComponent(codeEditor)?.defaultEditorOption || {}; this.nzConfigService.set(codeEditor, { defaultEditorOption: { ...defaultEditorOption, theme: dark ? vs-dark : vs } });CodeEditorConfig 参数表参数说明类型默认值assetsRoot组件从何处加载 monaco 资源string|SafeUrl-defaultEditorOption默认编辑器配置参考 monaco 的IEditorConstructionOptionsIEditorConstructionOptions{}onLoadmonaco 资源加载完成后的钩子此时及之后全局变量monaco可用monaco-editor 版本 ≥ 0.22.0 时需设置window.MonacoEnvironment { globalAPI: true }() void-onFirstEditorInit第一个 monaco 编辑器初始化时触发的钩子() void-onInit每次 monaco 编辑器初始化时触发的钩子() void-useStaticLoading是否静态加载 monacobooleanfalsenzEditorOption与defaultEditorOption的合并顺序在 code-editor.component.ts 中有明确定义{ ...默认配置, ...defaultEditorOption, ...自身传入的 nzEditorOption }即组件级配置优先级最高且任一变化都会通过updateOptions实时同步给 monaco 实例。全局配置在源码中的落地链路NzCodeEditorService在构造时读取codeEditor全局配置code-editor.service.ts并做了三件事若配置了monacoEnvironment将其挂到window.MonacoEnvironment这正是上述onLoad钩子说明中globalAPI: true对应的机制将defaultEditorOption作为初始默认值推入option$流通过onConfigChangeEventForComponent(codeEditor, ...)监听全局配置热更新_updateDefaultOption会合并新配置并在配置中出现theme时调用monaco.editor.setTheme(option.theme)code-editor.service.ts这也是全局改主题能即时生效的原因。onLoad、onFirstEditorInit、onInit三个钩子的触发顺序可在 code-editor.service.ts 中看到资源加载完成触发onLoad每个编辑器初始化时触发onInit其中第一个编辑器额外触发一次onFirstEditorInit通过firstEditorInitialized标志位保证只执行一次。源码级原理组件与 Angular 生态的协作细节双向绑定与事件循环nz-code-editor实现了ControlValueAccessorwriteValue负责把外部值写入编辑器code-editor.component.ts而编辑器内容的变更通过model.onDidChangeContent监听值发生变化时才ngZone.run(() this.onChange(value))重新进入 Angular 变更检测code-editor.component.ts。监听器返回的 disposable 会在组件销毁时dispose()避免「组件 → monaco → 组件」的循环引用阻碍 GC见 code-editor.component.ts 注释。光标位置保留monaco 的setValue会把光标重置到文档开头组件为此实现了preservePositionAndSelections()先记录getPosition()与getSelections()更新内容后再恢复code-editor.component.ts保证表单驱动更新不会打扰用户正在编辑的位置。自适应布局组件监听window的resize事件300ms 防抖并暴露layout()方法内部通过resize$流对容器宽高做distinctUntilChanged 50ms 防抖后调用editorInstance.layout()code-editor.component.ts。容器尺寸变化或全屏切换后调用layout()即可让编辑器重绘。关于类型组件公开的类型定义位于 typings.tsNzEditorMode normal | diff、EditorOptions/DiffEditorOptions分别对应 monaco 的IStandaloneEditorConstructionOptions与IDiffEditorConstructionOptions、以及JoinedEditorOptions联合类型。所有公开 API 通过 public-api.ts 统一导出组件、模块、service、typings。常见问题与注意事项SSR 环境组件在ngAfterViewInit中检测到非浏览器环境会直接跳过初始化code-editor.component.ts无需额外处理但 SSR 页面中不会渲染出编辑器实例静态加载与资源复制的互斥选择了静态加载useStaticLoading: true后不要再在angular.json中配置 monaco 的 assets 输出monaco 版本兼容monaco-editor ≥ 0.22.0 时onLoad钩子可正常使用全局monaco变量但需要提前设置window.MonacoEnvironment { globalAPI: true }全控制模式的数据流全控制模式下组件不再管理 TextModel 与值同步ngModel绑定不再生效必须通过nzEditorInitialized拿到实例后手动管理组件为实验性功能文档 front-matter 中标记了experimental: true升级 ng-zorro-antd 主版本时需关注该组件的 API 变更可对照 migration-v22 等迁移文档。小结nz-code-editor用一层薄封装解决了 monaco-editor 在 Angular 中的资源加载、实例管理、表单联动与变更检测协作问题。接入的核心决策点只有一个根据你是否依赖 AMD 加载器在「动态加载」默认配合angular.jsonassets 或 CDNassetsRoot与「静态加载」useStaticLoading: true monaco webpack 插件之间二选一其余场景——diff 对比、全控制、全局主题、loading 与工具栏——均由文档与源码给出了清晰可验证的答案。配合仓库中的 demo 目录 与 单元测试 阅读即可快速在自己的 Angular 项目中落地一个生产级的代码编辑器。赞分享UI组件前端【免费下载链接】ng-zorro-antdAngular UI Component Library based on Ant Design项目地址https://gitcode.com/gh_mirrors/ng/ng-zorro-antd点击查看免费下载相关推荐ng-zorro-antd Code Editor 组件完全指南基于 monaco-editor 的 Angular 代码编辑器集成方案ng zorro antd Code Editor 组件完全指南基于 monaco editor 的 Angular 代码编辑器集成方案 导读 nz codeUI组件前端ng-zorro-antd Code Editor 完全受控模式实战手动接管 Monaco TextModelng zorro antd Code Editor 完全受控模式实战手动接管 Monaco TextModel nz code editor 是 ng zorUI组件前端ng-zorro-antd Code Editor 复杂实战加载效果Loading与自定义工具条Toolkit的完整实现ng zorro antd Code Editor 复杂实战加载效果Loading与自定义工具条Toolkit的完整实现 nz code editorUI组件前端上一篇3个核心突破科研工作者的文献获取难题终极解决方案下一篇智能文献获取Zotero SciPDF插件的自动化PDF解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表