feat(editor): monaco-editor改成异步加载

This commit is contained in:
roymondchen 2026-03-12 17:27:07 +08:00
parent 0d698b20e7
commit 71d6dd9e38
6 changed files with 44 additions and 29 deletions

View File

@ -54,7 +54,7 @@
"@tmagic/utils": "workspace:*", "@tmagic/utils": "workspace:*",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"deep-object-diff": "^1.1.9", "deep-object-diff": "^1.1.9",
"emmet-monaco-es": "^5.6.1", "emmet-monaco-es": "^5.7.0",
"events": "^3.3.0", "events": "^3.3.0",
"gesto": "^1.19.4", "gesto": "^1.19.4",
"keycon": "^1.4.0", "keycon": "^1.4.0",

View File

@ -20,13 +20,14 @@
import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue'; import { computed, nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
import { FullScreen } from '@element-plus/icons-vue'; import { FullScreen } from '@element-plus/icons-vue';
import { throttle } from 'lodash-es'; import { throttle } from 'lodash-es';
import type * as Monaco from 'monaco-editor';
import serialize from 'serialize-javascript'; import serialize from 'serialize-javascript';
import { TMagicButton } from '@tmagic/design'; import { TMagicButton } from '@tmagic/design';
import MIcon from '@editor/components/Icon.vue'; import MIcon from '@editor/components/Icon.vue';
import { getEditorConfig } from '@editor/utils/config'; import { getEditorConfig } from '@editor/utils/config';
import monaco from '@editor/utils/monaco-editor'; import loadMonaco from '@editor/utils/monaco-editor';
defineOptions({ defineOptions({
name: 'MEditorCodeEditor', name: 'MEditorCodeEditor',
@ -38,7 +39,7 @@ const props = withDefaults(
modifiedValues?: any; modifiedValues?: any;
type?: 'diff'; type?: 'diff';
language?: string; language?: string;
options?: monaco.editor.IStandaloneEditorConstructionOptions; options?: Monaco.editor.IStandaloneEditorConstructionOptions;
height?: string; height?: string;
autoSave?: boolean; autoSave?: boolean;
parse?: boolean; parse?: boolean;
@ -99,7 +100,7 @@ const calculateExtraHeight = (): number => {
extraHeight = Math.max(editorRect.height - scrollableRect.height, 0); extraHeight = Math.max(editorRect.height - scrollableRect.height, 0);
// 使 // 使
if (extraHeight === 0) { if (extraHeight === 0 && monaco) {
const editorOptions = vsEditor.getOptions(); const editorOptions = vsEditor.getOptions();
const scrollBeyondLastLine = editorOptions.get(monaco.editor.EditorOption.scrollBeyondLastLine); const scrollBeyondLastLine = editorOptions.get(monaco.editor.EditorOption.scrollBeyondLastLine);
const padding = editorOptions.get(monaco.editor.EditorOption.padding); const padding = editorOptions.get(monaco.editor.EditorOption.padding);
@ -127,7 +128,7 @@ const setAutoHeight = (v = '') => {
// 使 // 使
let lineHeight = 20; let lineHeight = 20;
if (vsEditor) { if (vsEditor && monaco) {
const editorOptions = vsEditor.getOptions(); const editorOptions = vsEditor.getOptions();
lineHeight = editorOptions.get(monaco.editor.EditorOption.lineHeight) || 20; lineHeight = editorOptions.get(monaco.editor.EditorOption.lineHeight) || 20;
} }
@ -188,8 +189,9 @@ const parseCode = (v: string | any, language: string): any => {
return getEditorConfig('parseDSL')(v); return getEditorConfig('parseDSL')(v);
}; };
let vsEditor: monaco.editor.IStandaloneCodeEditor | null = null; let monaco: typeof import('monaco-editor') | null = null;
let vsDiffEditor: monaco.editor.IStandaloneDiffEditor | null = null; let vsEditor: Monaco.editor.IStandaloneCodeEditor | null = null;
let vsDiffEditor: Monaco.editor.IStandaloneDiffEditor | null = null;
const values = ref(''); const values = ref('');
const loading = ref(false); const loading = ref(false);
@ -207,6 +209,8 @@ const setEditorValue = (v: string | any, m: string | any) => {
setAutoHeight(values.value); setAutoHeight(values.value);
if (!monaco) return;
if (props.type === 'diff') { if (props.type === 'diff') {
const originalModel = monaco.editor.createModel(values.value, 'text/javascript'); const originalModel = monaco.editor.createModel(values.value, 'text/javascript');
const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript'); const modifiedModel = monaco.editor.createModel(toString(m, props.language), 'text/javascript');
@ -255,6 +259,8 @@ const init = async () => {
// //
cachedExtraHeight = null; cachedExtraHeight = null;
monaco = await loadMonaco();
const options = { const options = {
value: values.value, value: values.value,
language: props.language, language: props.language,
@ -264,7 +270,7 @@ const init = async () => {
}; };
if (props.type === 'diff') { if (props.type === 'diff') {
vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options); vsDiffEditor = await getEditorConfig('customCreateMonacoDiffEditor')(monaco!, codeEditorEl.value, options);
// diff // diff
vsDiffEditor.getModifiedEditor().onDidChangeModelContent(() => { vsDiffEditor.getModifiedEditor().onDidChangeModelContent(() => {
@ -274,7 +280,7 @@ const init = async () => {
} }
}); });
} else { } else {
vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options); vsEditor = await getEditorConfig('customCreateMonacoEditor')(monaco!, codeEditorEl.value, options);
// //
vsEditor.onDidChangeModelContent(() => { vsEditor.onDidChangeModelContent(() => {
@ -343,6 +349,7 @@ onBeforeUnmount(() => {
vsEditor = null; vsEditor = null;
vsDiffEditor = null; vsDiffEditor = null;
monaco = null;
// //
cachedExtraHeight = null; cachedExtraHeight = null;

View File

@ -18,6 +18,7 @@
import type { Component } from 'vue'; import type { Component } from 'vue';
import type EventEmitter from 'events'; import type EventEmitter from 'events';
import type * as Monaco from 'monaco-editor';
import Sortable, { type Options, type SortableEvent } from 'sortablejs'; import Sortable, { type Options, type SortableEvent } from 'sortablejs';
import type { PascalCasedProperties } from 'type-fest'; import type { PascalCasedProperties } from 'type-fest';
@ -32,8 +33,6 @@ import type {
UpdateDragEl, UpdateDragEl,
} from '@tmagic/stage'; } from '@tmagic/stage';
import Monaco from '@editor/utils/monaco-editor';
import type { CodeBlockService } from './services/codeBlock'; import type { CodeBlockService } from './services/codeBlock';
import type { ComponentListService } from './services/componentList'; import type { ComponentListService } from './services/componentList';
import type { DataSourceService } from './services/dataSource'; import type { DataSourceService } from './services/dataSource';
@ -121,15 +120,15 @@ export type GetConfig = (config: FormConfig) => Promise<FormConfig> | FormConfig
export interface EditorInstallOptions { export interface EditorInstallOptions {
parseDSL: <T = any>(dsl: string) => T; parseDSL: <T = any>(dsl: string) => T;
customCreateMonacoEditor: ( customCreateMonacoEditor: (
monaco: typeof Monaco, monaco: typeof import('monaco-editor'),
codeEditorEl: HTMLElement, codeEditorEl: HTMLElement,
options: Monaco.editor.IStandaloneEditorConstructionOptions & { editorCustomType?: string }, options: Monaco.editor.IStandaloneEditorConstructionOptions & { editorCustomType?: string },
) => Monaco.editor.IStandaloneCodeEditor; ) => Promise<Monaco.editor.IStandaloneCodeEditor> | Monaco.editor.IStandaloneCodeEditor;
customCreateMonacoDiffEditor: ( customCreateMonacoDiffEditor: (
monaco: typeof Monaco, monaco: typeof import('monaco-editor'),
codeEditorEl: HTMLElement, codeEditorEl: HTMLElement,
options: Monaco.editor.IStandaloneEditorConstructionOptions & { editorCustomType?: string }, options: Monaco.editor.IStandaloneEditorConstructionOptions & { editorCustomType?: string },
) => Monaco.editor.IStandaloneDiffEditor; ) => Promise<Monaco.editor.IStandaloneDiffEditor> | Monaco.editor.IStandaloneDiffEditor;
[key: string]: any; [key: string]: any;
} }

View File

@ -1,8 +1,15 @@
import { emmetCSS, emmetHTML } from 'emmet-monaco-es'; let cached: Promise<typeof import('monaco-editor')> | undefined;
import * as monaco from 'monaco-editor';
// 注册emmet插件 export default () => {
if (!cached) {
cached = Promise.all([import('emmet-monaco-es'), import('monaco-editor')]).then(([emmet, monaco]) => {
const { emmetHTML, emmetCSS } = emmet;
emmetHTML(monaco); emmetHTML(monaco);
emmetCSS(monaco, ['css', 'scss']); emmetCSS(monaco, ['css', 'scss']);
export default monaco; return monaco;
});
}
return cached;
};

View File

@ -47,6 +47,7 @@ export const numberOptions = [
export const styleTabConfig: TabPaneConfig = { export const styleTabConfig: TabPaneConfig = {
title: '样式', title: '样式',
lazy: true,
display: ({ services }: any) => !(services.uiService.get('showStylePanel') ?? true), display: ({ services }: any) => !(services.uiService.get('showStylePanel') ?? true),
items: [ items: [
{ {
@ -114,6 +115,7 @@ export const styleTabConfig: TabPaneConfig = {
export const eventTabConfig: TabPaneConfig = { export const eventTabConfig: TabPaneConfig = {
title: '事件', title: '事件',
lazy: true,
items: [ items: [
{ {
name: 'events', name: 'events',

16
pnpm-lock.yaml generated
View File

@ -327,8 +327,8 @@ importers:
specifier: ^1.1.9 specifier: ^1.1.9
version: 1.1.9 version: 1.1.9
emmet-monaco-es: emmet-monaco-es:
specifier: ^5.6.1 specifier: ^5.7.0
version: 5.6.1(monaco-editor@0.48.0) version: 5.7.0(monaco-editor@0.48.0)
events: events:
specifier: ^3.3.0 specifier: ^3.3.0
version: 3.3.0 version: 3.3.0
@ -4166,8 +4166,8 @@ packages:
peerDependencies: peerDependencies:
vue: ^3.2.0 vue: ^3.2.0
emmet-monaco-es@5.6.1: emmet-monaco-es@5.7.0:
resolution: {integrity: sha512-Bdh0CJaG2NvcwCgRYQMBqtIiDI9/BwYNTFUnYd68OXC8DXNcAVLsIKIEnDhOGYtEO60Knf2OgMrL7UDQ5zh1yA==} resolution: {integrity: sha512-q8jtgsEWWaXHnAJ6HAcwMB7WHraRtf032TWpeOpN6SGLtwxr7hd6RgF3Kbj2rPxb6Q19fYVVafAFODYRYUS8NQ==}
peerDependencies: peerDependencies:
monaco-editor: '>=0.22.0' monaco-editor: '>=0.22.0'
@ -8380,7 +8380,7 @@ snapshots:
'@tmagic/utils': 1.7.2(@tmagic/schema@1.7.6(typescript@5.9.3))(typescript@5.9.3) '@tmagic/utils': 1.7.2(@tmagic/schema@1.7.6(typescript@5.9.3))(typescript@5.9.3)
buffer: 6.0.3 buffer: 6.0.3
deep-object-diff: 1.1.9 deep-object-diff: 1.1.9
emmet-monaco-es: 5.6.1(monaco-editor@0.55.1) emmet-monaco-es: 5.7.0(monaco-editor@0.55.1)
events: 3.3.0 events: 3.3.0
gesto: 1.19.4 gesto: 1.19.4
keycon: 1.4.0 keycon: 1.4.0
@ -8407,7 +8407,7 @@ snapshots:
'@tmagic/utils': 1.7.6(@tmagic/schema@1.7.6(typescript@5.9.3))(typescript@5.9.3) '@tmagic/utils': 1.7.6(@tmagic/schema@1.7.6(typescript@5.9.3))(typescript@5.9.3)
buffer: 6.0.3 buffer: 6.0.3
deep-object-diff: 1.1.9 deep-object-diff: 1.1.9
emmet-monaco-es: 5.6.1(monaco-editor@0.55.1) emmet-monaco-es: 5.7.0(monaco-editor@0.55.1)
events: 3.3.0 events: 3.3.0
gesto: 1.19.4 gesto: 1.19.4
keycon: 1.4.0 keycon: 1.4.0
@ -9848,12 +9848,12 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
emmet-monaco-es@5.6.1(monaco-editor@0.48.0): emmet-monaco-es@5.7.0(monaco-editor@0.48.0):
dependencies: dependencies:
emmet: 2.4.11 emmet: 2.4.11
monaco-editor: 0.48.0 monaco-editor: 0.48.0
emmet-monaco-es@5.6.1(monaco-editor@0.55.1): emmet-monaco-es@5.7.0(monaco-editor@0.55.1):
dependencies: dependencies:
emmet: 2.4.11 emmet: 2.4.11
monaco-editor: 0.55.1 monaco-editor: 0.55.1