如何在AngularJS网站中实现MonacoEditor的懒加载?
AngularJS中懒加载Monaco Editor的实现方案
我来给你分享一个在AngularJS项目中懒加载Monaco Editor的靠谱方案,亲测在老项目中稳定可行~
1. 先移除静态加载的资源
首先把你原来在index.html里直接引入的Monaco相关样式和脚本全部删掉,我们要改成动态按需加载:
移除这些代码:
<link rel="stylesheet" data-name="vs/editor/editor.main" href="/monaco-editor/min/vs/editor/editor.main.css" /> <script src="/monaco-editor/min/vs/loader.js"></script> <script src="/monaco-editor/min/vs/editor/editor.main.nls.js"></script> <script src="/monaco-editor/min/vs/editor/editor.main.js"></script> <script> require.config({ paths: { 'vs': '/monaco-editor/m... </script>
2. 创建单例懒加载服务
AngularJS的服务是单例的,非常适合用来处理资源加载逻辑,避免重复请求。我们创建一个monacoLoader服务来统一管理Monaco的加载:
angular.module('yourApp') // 替换成你的实际应用模块名 .factory('monacoLoader', ['$q', '$document', '$window', function($q, $document, $window) { var loadDeferred = $q.defer(); var isMonacoLoaded = false; // 辅助函数:加载样式文件 function loadStyleSheet(url) { const link = $document[0].createElement('link'); link.rel = 'stylesheet'; link.href = url; $document[0].head.appendChild(link); } // 核心加载逻辑 this.load = function() { // 如果已经加载过,直接返回已resolved的Promise if (isMonacoLoaded) { return $q.resolve(); } // 1. 先加载编辑器样式 loadStyleSheet('/monaco-editor/min/vs/editor/editor.main.css'); // 2. 加载Monaco的loader脚本 const loaderScript = $document[0].createElement('script'); loaderScript.type = 'text/javascript'; loaderScript.src = '/monaco-editor/min/vs/loader.js'; loaderScript.onload = function() { // 3. 配置require路径(这里要和你的Monaco文件路径匹配) $window.require.config({ paths: { 'vs': '/monaco-editor/min/vs' } }); // 4. 通过require加载Monaco主文件(会自动依赖加载editor.main.nls.js) $window.require(['vs/editor/editor.main'], function() { isMonacoLoaded = true; loadDeferred.resolve(); }, function(error) { loadDeferred.reject(`加载Monaco失败:${error}`); }); }; loaderScript.onerror = function() { loadDeferred.reject('加载Monaco loader脚本失败'); }; $document[0].body.appendChild(loaderScript); return loadDeferred.promise; }; return this; }]);
3. 用指令封装编辑器组件
接下来创建一个可复用的monacoEditor指令,当指令所在的DOM元素被渲染时,才触发Monaco的加载和初始化:
angular.module('yourApp') .directive('monacoEditor', ['monacoLoader', function(monacoLoader) { return { restrict: 'E', scope: { // 双向绑定编辑器内容 content: '=', // 可选:指定编辑语言,比如javascript、html等 language: '@?' }, link: function(scope, element) { // 设置编辑器容器的基础样式(必须要有宽高) element.css({ width: '100%', height: '500px', border: '1px solid #eee' }); // 调用加载服务,等待Monaco就绪 monacoLoader.load().then(function() { // 初始化Monaco编辑器 const editor = monaco.editor.create(element[0], { value: scope.content || '', language: scope.language || 'javascript', theme: 'vs-light' // 可选:指定主题,比如vs-dark }); // 同步scope内容到编辑器 scope.$watch('content', function(newVal) { if (newVal !== editor.getValue()) { editor.setValue(newVal); } }); // 同步编辑器内容到scope editor.onDidChangeModelContent(function() { scope.$apply(function() { scope.content = editor.getValue(); }); }); // 页面销毁时清理编辑器,避免内存泄漏 scope.$on('$destroy', function() { editor.dispose(); }); }).catch(function(error) { console.error(error); element.html('<p style="padding: 20px; color: #dc3545;">代码编辑器加载失败,请稍后重试</p>'); }); } }; }]);
4. 在页面中使用编辑器
现在你可以在需要的地方直接使用这个指令,只有当这个DOM元素被渲染时,Monaco才会开始加载:
<!-- 在你的视图模板中 --> <monaco-editor content="vm.editorContent" language="html"></monaco-editor>
一些注意事项
- 路径匹配:确保代码中的
/monaco-editor/min/vs路径和你项目中Monaco Editor的实际文件路径一致。 - 容器样式:编辑器容器必须设置宽高,否则Monaco无法正常渲染。
- 重复加载防护:服务中的
isMonacoLoaded标记确保Monaco资源只会被加载一次,即使多个地方调用load()方法。 - 错误处理:代码中加入了错误捕获逻辑,加载失败时会给用户友好提示。
内容的提问来源于stack exchange,提问作者SoftTimur
相关产品推荐
相关产品推荐

