diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index a29ae0156..5fb7cd392 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -1,4 +1,5 @@ import { obx, autorun, computed, getPublicPath, hotkey, focusTracker, globalContext, Editor } from '@ali/lowcode-editor-core'; +import { EventEmitter } from 'events'; import { ISimulatorHost, Component, NodeInstance, ComponentInstance } from '../simulator'; import Viewport from './viewport'; import { createSimulator } from './create-simulator'; @@ -72,10 +73,12 @@ const defaultEnvironment = [ export class BuiltinSimulatorHost implements ISimulatorHost { readonly isSimulator = true; - - constructor(readonly document: DocumentModel) {} - readonly designer = this.document.designer; + private emitter: EventEmitter; + + constructor(readonly document: DocumentModel) { + this.emitter = new EventEmitter(); + } @computed get device(): string { return this.get('device') || 'default'; @@ -126,6 +129,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost void; firstRun: boolean }) => void) { this._renderer = renderer; + this.emitter.emit('lowcode_engine_renderer_connect', renderer); return autorun(fn as any, true); } @@ -1130,6 +1134,13 @@ export class BuiltinSimulatorHost implements ISimulatorHost void): () => void { + this.emitter.on('lowcode_engine_renderer_connect', fn); + return () => { + this.emitter.removeListener('lowcode_engine_renderer_connect', fn); + }; + } } function isHTMLTag(name: string) { diff --git a/packages/designer/src/builtin-simulator/renderer.ts b/packages/designer/src/builtin-simulator/renderer.ts index 3994d67c4..7e46679e4 100644 --- a/packages/designer/src/builtin-simulator/renderer.ts +++ b/packages/designer/src/builtin-simulator/renderer.ts @@ -14,6 +14,7 @@ export interface BuiltinSimulatorRenderer { setCopyState(state: boolean): void; clearState(): void; run(): void; + onRendered(fn: () => void): () => void; } export function isSimulatorRenderer(obj: any): obj is BuiltinSimulatorRenderer { diff --git a/packages/designer/src/document/document-model.ts b/packages/designer/src/document/document-model.ts index 3f4805e83..3387df978 100644 --- a/packages/designer/src/document/document-model.ts +++ b/packages/designer/src/document/document-model.ts @@ -1,5 +1,6 @@ import { computed, obx } from '@ali/lowcode-editor-core'; import { NodeData, isJSExpression, isDOMText, NodeSchema, isNodeSchema, RootSchema } from '@ali/lowcode-types'; +import { EventEmitter } from 'events'; import { Project } from '../project'; import { ISimulatorHost } from '../simulator'; import { ComponentMeta } from '../component-meta'; @@ -40,6 +41,7 @@ export class DocumentModel { @obx.val private nodes = new Set(); private seqId = 0; private _simulator?: ISimulatorHost; + private emitter: EventEmitter; /** * 模拟器 @@ -75,6 +77,7 @@ export class DocumentModel { console.info(this.willPurgeSpace); }, true); */ + this.emitter = new EventEmitter(); if (!schema) { this._blank = true; @@ -342,6 +345,11 @@ export class DocumentModel { // TODO: 多设备 simulator 支持 this._simulator = simulator; // TODO: emit simulator mounted + this._simulator?.onRendererConnect((renderer) => { + this.emitter.emit('lowcode_engine_renderer_ready', { + renderer, + }); + }) } // FIXME: does needed? @@ -499,6 +507,13 @@ export class DocumentModel { get root() { return this.rootNode; } + + onRendererReady(fn: (args: any) => void): () => void { + this.emitter.on('lowcode_engine_renderer_ready', fn); + return () => { + this.emitter.removeListener('lowcode_engine_renderer_ready', fn); + }; + } } export function isDocumentModel(obj: any): obj is DocumentModel { diff --git a/packages/designer/src/simulator.ts b/packages/designer/src/simulator.ts index f051bc1f8..9f7e1bb6f 100644 --- a/packages/designer/src/simulator.ts +++ b/packages/designer/src/simulator.ts @@ -143,6 +143,8 @@ export interface ISimulatorHost

extends ISensor { findDOMNodes(instance: ComponentInstance, selector?: string): Array | null; + onRendererConnect(fn: (renderer: any) => void): () => void; + /** * 销毁 */ diff --git a/packages/editor-preset-vision/src/editor.ts b/packages/editor-preset-vision/src/editor.ts index 2e75c0366..e8997e919 100644 --- a/packages/editor-preset-vision/src/editor.ts +++ b/packages/editor-preset-vision/src/editor.ts @@ -5,6 +5,8 @@ import { Designer, LiveEditing, TransformStage, Node } from '@ali/lowcode-design import Outline, { OutlineBackupPane, getTreeMaster } from '@ali/lowcode-plugin-outline-pane'; import { toCss } from '@ali/vu-css-style'; import logger from '@ali/vu-logger'; +import bus from './bus'; +import { VE_EVENTS } from './base/const'; import DesignerPlugin from '@ali/lowcode-plugin-designer'; import { Skeleton, SettingsPrimaryPane } from '@ali/lowcode-editor-skeleton'; @@ -23,6 +25,15 @@ export const designer = new Designer({ editor: editor }); editor.set(Designer, designer); editor.set('designer', designer); +designer.project.onCurrentDocumentChange((doc) => { + doc.onRendererReady((args) => { + const { renderer } = args; + renderer.onRendered(() => { + bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY); + }); + }) +}); + // 节点 props 初始化 designer.addPropsReducer((props, node) => { // run initials diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index c5441de93..620077a71 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -1,5 +1,6 @@ import React, { createElement, ReactInstance, ComponentType, ReactElement } from 'react'; import { render as reactRender } from 'react-dom'; +import { EventEmitter } from 'events'; import { host } from './host'; import SimulatorRendererView from './renderer-view'; import { computed, obx } from '@recore/obx'; @@ -17,10 +18,14 @@ import Leaf from './builtin-components/leaf'; export class SimulatorRenderer implements BuiltinSimulatorRenderer { readonly isSimulatorRenderer = true; private dispose?: () => void; + private emitter: EventEmitter; + constructor() { if (!host) { return; } + + this.emitter = new EventEmitter(); this.dispose = host.connect(this, () => { // sync layout config @@ -286,6 +291,14 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer { document.body.classList.add('engine-document'); // important! Stylesheet.invoke depends reactRender(createElement(SimulatorRendererView, { renderer: this }), container); + this.emitter.emit('lowcode_engine_render_run'); + } + + onRendered(fn: () => void): () => void { + this.emitter.on('lowcode_engine_render_run', fn); + return () => { + this.emitter.removeListener('lowcode_engine_render_run', fn); + }; } }