mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-14 21:12:53 +00:00
feat: support SPA mode
This commit is contained in:
parent
0bcd9ff782
commit
1f9150e4b2
@ -98,7 +98,7 @@ export function createSimulator(
|
|||||||
doc.close();
|
doc.close();
|
||||||
|
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const renderer = win.SimulatorRenderer || host.renderer;
|
const renderer = win.SimulatorRenderer;
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
return resolve(renderer);
|
return resolve(renderer);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -850,7 +850,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
|
|
||||||
// filter with context
|
// filter with context
|
||||||
return instances.filter((instance) => {
|
return instances.filter((instance) => {
|
||||||
return this.getClosestNodeInstance(instance, context.nodeId)?.instance === context.instance;
|
return this.getClosestNodeInstance(instance, context?.nodeId)?.instance === context.instance;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { createElement } from 'react';
|
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 { globalContext, Editor, engineConfig, EngineOptions } from '@alilc/lowcode-editor-core';
|
||||||
import {
|
import {
|
||||||
Designer,
|
Designer,
|
||||||
@ -16,7 +16,7 @@ import {
|
|||||||
|
|
||||||
import Outline, { OutlineBackupPane, getTreeMaster } from '@alilc/lowcode-plugin-outline-pane';
|
import Outline, { OutlineBackupPane, getTreeMaster } from '@alilc/lowcode-plugin-outline-pane';
|
||||||
import DesignerPlugin from '@alilc/lowcode-plugin-designer';
|
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 { getLogger, isPlainObject } from '@alilc/lowcode-utils';
|
||||||
import './modules/live-editing';
|
import './modules/live-editing';
|
||||||
import utils from './modules/utils';
|
import utils from './modules/utils';
|
||||||
@ -184,7 +184,8 @@ engineConfig.set('isOpenSource', isOpenSource);
|
|||||||
await plugins.register(defaultPanelRegistry);
|
await plugins.register(defaultPanelRegistry);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
let engineInited = false;
|
// container which will host LowCodeEngine DOM
|
||||||
|
let engineContainer: HTMLElement;
|
||||||
// @ts-ignore webpack Define variable
|
// @ts-ignore webpack Define variable
|
||||||
export const version = VERSION_PLACEHOLDER;
|
export const version = VERSION_PLACEHOLDER;
|
||||||
engineConfig.set('ENGINE_VERSION', version);
|
engineConfig.set('ENGINE_VERSION', version);
|
||||||
@ -193,23 +194,22 @@ export async function init(
|
|||||||
options?: EngineOptions,
|
options?: EngineOptions,
|
||||||
pluginPreference?: PluginPreference,
|
pluginPreference?: PluginPreference,
|
||||||
) {
|
) {
|
||||||
if (engineInited) return;
|
await destroy();
|
||||||
engineInited = true;
|
|
||||||
let engineOptions = null;
|
let engineOptions = null;
|
||||||
let engineContainer = null;
|
|
||||||
if (isPlainObject(container)) {
|
if (isPlainObject(container)) {
|
||||||
engineOptions = container;
|
engineOptions = container;
|
||||||
engineContainer = document.createElement('div');
|
engineContainer = document.createElement('div');
|
||||||
|
engineContainer.id = 'engine';
|
||||||
document.body.appendChild(engineContainer);
|
document.body.appendChild(engineContainer);
|
||||||
} else {
|
} else {
|
||||||
engineOptions = options;
|
engineOptions = options;
|
||||||
engineContainer = container;
|
engineContainer = container;
|
||||||
if (!container) {
|
if (!container) {
|
||||||
engineContainer = document.createElement('div');
|
engineContainer = document.createElement('div');
|
||||||
|
engineContainer.id = 'engine';
|
||||||
document.body.appendChild(engineContainer);
|
document.body.appendChild(engineContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
engineContainer.id = 'engine';
|
|
||||||
engineConfig.setEngineOptions(engineOptions as any);
|
engineConfig.setEngineOptions(engineOptions as any);
|
||||||
|
|
||||||
await plugins.init(pluginPreference as any);
|
await plugins.init(pluginPreference as any);
|
||||||
@ -222,3 +222,17 @@ export async function init(
|
|||||||
engineContainer,
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { getClosestNode, isFromVC, isReactComponent } from '@alilc/lowcode-utils
|
|||||||
import { GlobalEvent } from '@alilc/lowcode-types';
|
import { GlobalEvent } from '@alilc/lowcode-types';
|
||||||
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
|
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
|
||||||
import { host } from './host';
|
import { host } from './host';
|
||||||
|
import { isRendererDetached } from './utils/misc';
|
||||||
import './renderer.less';
|
import './renderer.less';
|
||||||
|
|
||||||
// patch cloneElement avoid lost keyProps
|
// patch cloneElement avoid lost keyProps
|
||||||
@ -170,14 +170,12 @@ class Renderer extends Component<{
|
|||||||
this.startTime = Date.now();
|
this.startTime = Date.now();
|
||||||
this.schemaChangedSymbol = false;
|
this.schemaChangedSymbol = false;
|
||||||
|
|
||||||
if (!container.autoRender) return null;
|
if (!container.autoRender || isRendererDetached()) return null;
|
||||||
return (
|
return (
|
||||||
<LowCodeRenderer
|
<LowCodeRenderer
|
||||||
locale={locale}
|
locale={locale}
|
||||||
messages={messages}
|
messages={messages}
|
||||||
schema={documentInstance.schema}
|
schema={documentInstance.schema}
|
||||||
deltaData={documentInstance.deltaData}
|
|
||||||
deltaMode={documentInstance.deltaMode}
|
|
||||||
components={container.components}
|
components={container.components}
|
||||||
appHelper={container.context}
|
appHelper={container.context}
|
||||||
designMode={designMode}
|
designMode={designMode}
|
||||||
|
|||||||
@ -51,24 +51,6 @@ export class DocumentInstance {
|
|||||||
return this._components;
|
return this._components;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 本次的变更数据
|
|
||||||
*/
|
|
||||||
@obx.ref private _deltaData: any = {};
|
|
||||||
|
|
||||||
@computed get deltaData(): any {
|
|
||||||
return this._deltaData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否使用增量模式
|
|
||||||
*/
|
|
||||||
@obx.ref private _deltaMode: boolean = false;
|
|
||||||
|
|
||||||
@computed get deltaMode(): boolean {
|
|
||||||
return this._deltaMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// context from: utils、constants、history、location、match
|
// context from: utils、constants、history、location、match
|
||||||
@obx.ref private _appContext = {};
|
@obx.ref private _appContext = {};
|
||||||
|
|
||||||
@ -116,7 +98,7 @@ export class DocumentInstance {
|
|||||||
return this.document.id;
|
return this.document.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private unmountIntance(id: string, instance: ReactInstance) {
|
private unmountInstance(id: string, instance: ReactInstance) {
|
||||||
const instances = this.instancesMap.get(id);
|
const instances = this.instancesMap.get(id);
|
||||||
if (instances) {
|
if (instances) {
|
||||||
const i = instances.indexOf(instance);
|
const i = instances.indexOf(instance);
|
||||||
@ -144,11 +126,11 @@ export class DocumentInstance {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const unmountIntance = this.unmountIntance.bind(this);
|
const unmountInstance = this.unmountInstance.bind(this);
|
||||||
const origId = (instance as any)[SYMBOL_VNID];
|
const origId = (instance as any)[SYMBOL_VNID];
|
||||||
if (origId && origId !== id) {
|
if (origId && origId !== id) {
|
||||||
// 另外一个节点的 instance 在此被复用了,需要从原来地方卸载
|
// 另外一个节点的 instance 在此被复用了,需要从原来地方卸载
|
||||||
unmountIntance(origId, instance);
|
unmountInstance(origId, instance);
|
||||||
}
|
}
|
||||||
if (isElement(instance)) {
|
if (isElement(instance)) {
|
||||||
cacheReactKey(instance);
|
cacheReactKey(instance);
|
||||||
@ -160,7 +142,7 @@ export class DocumentInstance {
|
|||||||
}
|
}
|
||||||
// hack! delete instance from map
|
// hack! delete instance from map
|
||||||
const newUnmount = function (this: any) {
|
const newUnmount = function (this: any) {
|
||||||
unmountIntance(id, instance);
|
unmountInstance(id, instance);
|
||||||
origUnmount && origUnmount.call(this);
|
origUnmount && origUnmount.call(this);
|
||||||
};
|
};
|
||||||
(newUnmount as any).origUnmount = origUnmount;
|
(newUnmount as any).origUnmount = origUnmount;
|
||||||
|
|||||||
@ -24,3 +24,12 @@ export function getProjectUtils(librayMap: LibrayMap, utilsMetadata: UtilsMetada
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* judges if current simulator renderer deteched or not
|
||||||
|
* @returns detached or not
|
||||||
|
*/
|
||||||
|
export function isRendererDetached() {
|
||||||
|
// if current iframe detached from host document, the `window.parent` will be undefined.
|
||||||
|
return !window.parent;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user