From 1f9150e4b260d522bd7cb31497069b700a1e8576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LeoYuan=20=E8=A2=81=E5=8A=9B=E7=9A=93?= Date: Mon, 19 Sep 2022 20:31:33 +0800 Subject: [PATCH] feat: support SPA mode --- .../src/builtin-simulator/create-simulator.ts | 2 +- .../designer/src/builtin-simulator/host.ts | 2 +- packages/engine/src/engine-core.ts | 28 ++++++++++++++----- .../src/renderer-view.tsx | 6 ++-- .../react-simulator-renderer/src/renderer.ts | 26 +++-------------- .../src/utils/misc.ts | 9 ++++++ 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/packages/designer/src/builtin-simulator/create-simulator.ts b/packages/designer/src/builtin-simulator/create-simulator.ts index 2ee0320d8..007286e9c 100644 --- a/packages/designer/src/builtin-simulator/create-simulator.ts +++ b/packages/designer/src/builtin-simulator/create-simulator.ts @@ -98,7 +98,7 @@ export function createSimulator( doc.close(); return new Promise((resolve) => { - const renderer = win.SimulatorRenderer || host.renderer; + const renderer = win.SimulatorRenderer; if (renderer) { return resolve(renderer); } diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 4bf049f5b..2fadbbf1a 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -850,7 +850,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost { - return this.getClosestNodeInstance(instance, context.nodeId)?.instance === context.instance; + return this.getClosestNodeInstance(instance, context?.nodeId)?.instance === context.instance; }); } diff --git a/packages/engine/src/engine-core.ts b/packages/engine/src/engine-core.ts index 6a5ab108c..aad924324 100644 --- a/packages/engine/src/engine-core.ts +++ b/packages/engine/src/engine-core.ts @@ -1,5 +1,5 @@ import { createElement } from 'react'; -import { render } from 'react-dom'; +import { render, unmountComponentAtNode } from 'react-dom'; import { globalContext, Editor, engineConfig, EngineOptions } from '@alilc/lowcode-editor-core'; import { Designer, @@ -16,7 +16,7 @@ import { import Outline, { OutlineBackupPane, getTreeMaster } from '@alilc/lowcode-plugin-outline-pane'; import DesignerPlugin from '@alilc/lowcode-plugin-designer'; -import { Hotkey, Project, Skeleton, Setters, Material, Event } from '@alilc/lowcode-shell'; +import { Hotkey, Project, Skeleton, Setters, Material, Event, DocumentModel } from '@alilc/lowcode-shell'; import { getLogger, isPlainObject } from '@alilc/lowcode-utils'; import './modules/live-editing'; import utils from './modules/utils'; @@ -184,7 +184,8 @@ engineConfig.set('isOpenSource', isOpenSource); await plugins.register(defaultPanelRegistry); })(); -let engineInited = false; +// container which will host LowCodeEngine DOM +let engineContainer: HTMLElement; // @ts-ignore webpack Define variable export const version = VERSION_PLACEHOLDER; engineConfig.set('ENGINE_VERSION', version); @@ -193,23 +194,22 @@ export async function init( options?: EngineOptions, pluginPreference?: PluginPreference, ) { - if (engineInited) return; - engineInited = true; + await destroy(); let engineOptions = null; - let engineContainer = null; if (isPlainObject(container)) { engineOptions = container; engineContainer = document.createElement('div'); + engineContainer.id = 'engine'; document.body.appendChild(engineContainer); } else { engineOptions = options; engineContainer = container; if (!container) { engineContainer = document.createElement('div'); + engineContainer.id = 'engine'; document.body.appendChild(engineContainer); } } - engineContainer.id = 'engine'; engineConfig.setEngineOptions(engineOptions as any); await plugins.init(pluginPreference as any); @@ -222,3 +222,17 @@ export async function init( engineContainer, ); } + +export async function destroy() { + // remove all documents + const { documents } = project; + if (Array.isArray(documents) && documents.length > 0) { + documents.forEach(((doc: DocumentModel) => project.removeDocument(doc))); + } + + // TODO: delete plugins except for core plugins + + // unmount DOM container, this will trigger React componentWillUnmount lifeCycle, + // so necessary cleanups will be done. + engineContainer && unmountComponentAtNode(engineContainer); +} diff --git a/packages/react-simulator-renderer/src/renderer-view.tsx b/packages/react-simulator-renderer/src/renderer-view.tsx index e855d583d..d042a4fa9 100644 --- a/packages/react-simulator-renderer/src/renderer-view.tsx +++ b/packages/react-simulator-renderer/src/renderer-view.tsx @@ -8,7 +8,7 @@ import { getClosestNode, isFromVC, isReactComponent } from '@alilc/lowcode-utils import { GlobalEvent } from '@alilc/lowcode-types'; import { SimulatorRendererContainer, DocumentInstance } from './renderer'; import { host } from './host'; - +import { isRendererDetached } from './utils/misc'; import './renderer.less'; // patch cloneElement avoid lost keyProps @@ -170,14 +170,12 @@ class Renderer extends Component<{ this.startTime = Date.now(); this.schemaChangedSymbol = false; - if (!container.autoRender) return null; + if (!container.autoRender || isRendererDetached()) return null; return (