mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-19 05:48:17 +00:00
logic for multi documents one sim
This commit is contained in:
parent
1f8eccb75c
commit
45ffc98277
@ -1,9 +1,8 @@
|
|||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
import { observer } from '@ali/lowcode-editor-core';
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
import { BuiltinSimulatorHost, BuiltinSimulatorProps } from './host';
|
import { BuiltinSimulatorHost, BuiltinSimulatorProps } from './host';
|
||||||
import { DocumentModel } from '../document';
|
|
||||||
import { SimulatorContext } from './context';
|
|
||||||
import { BemTools } from './bem-tools';
|
import { BemTools } from './bem-tools';
|
||||||
|
import { Project } from '../project';
|
||||||
import './host.less';
|
import './host.less';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -11,12 +10,11 @@ import './host.less';
|
|||||||
Canvas(DeviceShell) 设备壳层,通过背景图片来模拟,通过设备预设样式改变宽度、高度及定位 CanvasViewport
|
Canvas(DeviceShell) 设备壳层,通过背景图片来模拟,通过设备预设样式改变宽度、高度及定位 CanvasViewport
|
||||||
CanvasViewport 页面编排场景中宽高不可溢出 Canvas 区
|
CanvasViewport 页面编排场景中宽高不可溢出 Canvas 区
|
||||||
Content(Shell) 内容外层,宽高紧贴 CanvasViewport,禁用边框,禁用 margin
|
Content(Shell) 内容外层,宽高紧贴 CanvasViewport,禁用边框,禁用 margin
|
||||||
ContentFrame 可设置宽高,在页面场景一般只设置框,高度拉伸贴合 Content
|
BemTools 辅助显示层,初始相对 Content 位置 0,0,紧贴 Canvas, 根据 Content 滚动位置,改变相对位置
|
||||||
Auxiliary 辅助显示层,初始相对 Content 位置 0,0,紧贴 Canvas, 根据 Content 滚动位置,改变相对位置
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type SimulatorHostProps = BuiltinSimulatorProps & {
|
type SimulatorHostProps = BuiltinSimulatorProps & {
|
||||||
documentContext: DocumentModel;
|
project: Project;
|
||||||
onMount?: (host: BuiltinSimulatorHost) => void;
|
onMount?: (host: BuiltinSimulatorHost) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,8 +22,8 @@ export class BuiltinSimulatorHostView extends Component<SimulatorHostProps> {
|
|||||||
readonly host: BuiltinSimulatorHost;
|
readonly host: BuiltinSimulatorHost;
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
const { documentContext } = this.props;
|
const { project } = this.props;
|
||||||
this.host = (documentContext.simulator as BuiltinSimulatorHost) || new BuiltinSimulatorHost(documentContext);
|
this.host = (project.simulator as BuiltinSimulatorHost) || new BuiltinSimulatorHost(project);
|
||||||
this.host.setProps(this.props);
|
this.host.setProps(this.props);
|
||||||
}
|
}
|
||||||
shouldComponentUpdate(nextProps: BuiltinSimulatorProps) {
|
shouldComponentUpdate(nextProps: BuiltinSimulatorProps) {
|
||||||
|
|||||||
@ -4,7 +4,17 @@ import Viewport from './viewport';
|
|||||||
import { createSimulator } from './create-simulator';
|
import { createSimulator } from './create-simulator';
|
||||||
import { Node, ParentalNode, DocumentModel, isNode, contains, isRootNode } from '../document';
|
import { Node, ParentalNode, DocumentModel, isNode, contains, isRootNode } from '../document';
|
||||||
import ResourceConsumer from './resource-consumer';
|
import ResourceConsumer from './resource-consumer';
|
||||||
import { AssetLevel, Asset, AssetList, assetBundle, assetItem, AssetType, isElement, isFormEvent } from '@ali/lowcode-utils';
|
import {
|
||||||
|
AssetLevel,
|
||||||
|
Asset,
|
||||||
|
AssetList,
|
||||||
|
assetBundle,
|
||||||
|
assetItem,
|
||||||
|
AssetType,
|
||||||
|
isElement,
|
||||||
|
isFormEvent,
|
||||||
|
hasOwnProperty,
|
||||||
|
} from '@ali/lowcode-utils';
|
||||||
import {
|
import {
|
||||||
DragObjectType,
|
DragObjectType,
|
||||||
isShaken,
|
isShaken,
|
||||||
@ -26,6 +36,7 @@ import { ComponentMetadata, ComponentSchema } from '@ali/lowcode-types';
|
|||||||
import { BuiltinSimulatorRenderer } from './renderer';
|
import { BuiltinSimulatorRenderer } from './renderer';
|
||||||
import clipboard from '../designer/clipboard';
|
import clipboard from '../designer/clipboard';
|
||||||
import { LiveEditing } from './live-editing/live-editing';
|
import { LiveEditing } from './live-editing/live-editing';
|
||||||
|
import { Project } from '../project';
|
||||||
|
|
||||||
export interface LibraryItem {
|
export interface LibraryItem {
|
||||||
package: string;
|
package: string;
|
||||||
@ -74,9 +85,9 @@ const defaultEnvironment = [
|
|||||||
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
|
export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProps> {
|
||||||
readonly isSimulator = true;
|
readonly isSimulator = true;
|
||||||
|
|
||||||
constructor(readonly document: DocumentModel) {}
|
constructor(readonly project: Project) {}
|
||||||
|
|
||||||
readonly designer = this.document.designer;
|
readonly designer = this.project.designer;
|
||||||
|
|
||||||
@computed get device(): string {
|
@computed get device(): string {
|
||||||
return this.get('device') || 'default';
|
return this.get('device') || 'default';
|
||||||
@ -326,7 +337,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
x.initEvent('click', true);
|
x.initEvent('click', true);
|
||||||
this._iframe?.dispatchEvent(x);
|
this._iframe?.dispatchEvent(x);
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (isFormEvent(e) || target?.closest('.next-input-group,.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,.next-number-picker,.next-radio-group,.next-range,.next-range-picker,.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,.next-year-picker,.next-breadcrumb-item,.next-calendar-header,.next-calendar-table')) {
|
if (
|
||||||
|
isFormEvent(e) ||
|
||||||
|
target?.closest(
|
||||||
|
'.next-input-group,.next-checkbox-group,.next-date-picker,.next-input,.next-month-picker,.next-number-picker,.next-radio-group,.next-range,.next-range-picker,.next-rating,.next-select,.next-switch,.next-time-picker,.next-upload,.next-year-picker,.next-breadcrumb-item,.next-calendar-header,.next-calendar-table',
|
||||||
|
)
|
||||||
|
) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
@ -392,7 +408,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
}
|
}
|
||||||
const node = nodeInst.node || this.document.rootNode;
|
const node = nodeInst.node || this.document.rootNode;
|
||||||
|
|
||||||
const rootElement = this.findDOMNodes(nodeInst.instance, node.componentMeta.rootSelector)?.find(item => item.contains(targetElement)) as HTMLElement;
|
const rootElement = this.findDOMNodes(nodeInst.instance, node.componentMeta.rootSelector)?.find((item) =>
|
||||||
|
item.contains(targetElement),
|
||||||
|
) as HTMLElement;
|
||||||
if (!rootElement) {
|
if (!rootElement) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -405,7 +423,6 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -490,12 +507,17 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return this.renderer?.createComponent(schema) || null;
|
return this.renderer?.createComponent(schema) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.val private instancesMap = new Map<string, ComponentInstance[]>();
|
@obx private instancesMap: {
|
||||||
setInstance(id: string, instances: ComponentInstance[] | null) {
|
[docId: string]: Map<string, ComponentInstance[]>;
|
||||||
|
} = {};
|
||||||
|
setInstance(docId: string, id: string, instances: ComponentInstance[] | null) {
|
||||||
|
if (hasOwnProperty(this.instancesMap, docId)) {
|
||||||
|
this.instancesMap[docId] = new Map();
|
||||||
|
}
|
||||||
if (instances == null) {
|
if (instances == null) {
|
||||||
this.instancesMap.delete(id);
|
this.instancesMap[docId].delete(id);
|
||||||
} else {
|
} else {
|
||||||
this.instancesMap.set(id, instances.slice());
|
this.instancesMap[docId].set(id, instances.slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,7 +525,9 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
* @see ISimulator
|
* @see ISimulator
|
||||||
*/
|
*/
|
||||||
getComponentInstances(node: Node): ComponentInstance[] | null {
|
getComponentInstances(node: Node): ComponentInstance[] | null {
|
||||||
return this.instancesMap.get(node.id) || null;
|
const docId = node.document.id;
|
||||||
|
|
||||||
|
return this.instancesMap[docId]?.get(node.id) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -792,10 +816,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
this.sensing = true;
|
this.sensing = true;
|
||||||
this.scroller.scrolling(e);
|
this.scroller.scrolling(e);
|
||||||
const dropContainer = this.getDropContainer(e);
|
const dropContainer = this.getDropContainer(e);
|
||||||
if (!dropContainer ||
|
if (!dropContainer) {
|
||||||
// too dirty
|
|
||||||
(typeof dropContainer.container?.componentMeta?.prototype?.options?.canDropIn === 'function' &&
|
|
||||||
!dropContainer.container?.componentMeta?.prototype?.options?.canDropIn(e.dragObject.nodes[0]))) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,7 +847,12 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
event: e,
|
event: e,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (e.dragObject && e.dragObject.nodes && e.dragObject.nodes.length && e.dragObject.nodes[0].getPrototype()?.isModal()) {
|
if (
|
||||||
|
e.dragObject &&
|
||||||
|
e.dragObject.nodes &&
|
||||||
|
e.dragObject.nodes.length &&
|
||||||
|
e.dragObject.nodes[0].getPrototype()?.isModal()
|
||||||
|
) {
|
||||||
return this.designer.createLocation({
|
return this.designer.createLocation({
|
||||||
target: this.document.rootNode,
|
target: this.document.rootNode,
|
||||||
detail,
|
detail,
|
||||||
|
|||||||
@ -3,9 +3,7 @@ import { ComponentSchema } from '@ali/lowcode-types';
|
|||||||
|
|
||||||
export interface BuiltinSimulatorRenderer {
|
export interface BuiltinSimulatorRenderer {
|
||||||
readonly isSimulatorRenderer: true;
|
readonly isSimulatorRenderer: true;
|
||||||
createComponent(schema: ComponentSchema): Component | null;
|
|
||||||
getComponent(componentName: string): Component;
|
getComponent(componentName: string): Component;
|
||||||
getComponentInstances(id: string): ComponentInstance[] | null;
|
|
||||||
getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null;
|
getClosestNodeInstance(from: ComponentInstance, nodeId?: string): NodeInstance<ComponentInstance> | null;
|
||||||
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;
|
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;
|
||||||
getClientRects(element: Element | Text): DOMRect[];
|
getClientRects(element: Element | Text): DOMRect[];
|
||||||
|
|||||||
@ -348,7 +348,7 @@ export class Designer {
|
|||||||
|
|
||||||
@obx.ref private _simulatorProps?: object | ((document: DocumentModel) => object);
|
@obx.ref private _simulatorProps?: object | ((document: DocumentModel) => object);
|
||||||
|
|
||||||
@computed get simulatorProps(): object | ((document: DocumentModel) => object) {
|
@computed get simulatorProps(): object | ((project: Project) => object) {
|
||||||
return this._simulatorProps || {};
|
return this._simulatorProps || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,6 @@ export class DocumentModel {
|
|||||||
private nodesMap = new Map<string, Node>();
|
private nodesMap = new Map<string, Node>();
|
||||||
@obx.val private nodes = new Set<Node>();
|
@obx.val private nodes = new Set<Node>();
|
||||||
private seqId = 0;
|
private seqId = 0;
|
||||||
private _simulator?: ISimulatorHost;
|
|
||||||
private emitter: EventEmitter;
|
private emitter: EventEmitter;
|
||||||
private rootNodeVisitorMap: { [visitorName: string]: any } = {};
|
private rootNodeVisitorMap: { [visitorName: string]: any } = {};
|
||||||
private modalNodesManager: ModalNodesManager;
|
private modalNodesManager: ModalNodesManager;
|
||||||
@ -50,7 +49,7 @@ export class DocumentModel {
|
|||||||
* 模拟器
|
* 模拟器
|
||||||
*/
|
*/
|
||||||
get simulator(): ISimulatorHost | null {
|
get simulator(): ISimulatorHost | null {
|
||||||
return this._simulator || null;
|
return this.project.simulator;
|
||||||
}
|
}
|
||||||
|
|
||||||
get fileName(): string {
|
get fileName(): string {
|
||||||
@ -320,27 +319,6 @@ export class DocumentModel {
|
|||||||
return !this.history.isSavePoint();
|
return !this.history.isSavePoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 提供给模拟器的参数
|
|
||||||
*/
|
|
||||||
@computed get simulatorProps(): object {
|
|
||||||
let simulatorProps = this.designer.simulatorProps;
|
|
||||||
if (typeof simulatorProps === 'function') {
|
|
||||||
simulatorProps = simulatorProps(this);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...simulatorProps,
|
|
||||||
documentContext: this,
|
|
||||||
onMount: this.mountSimulator.bind(this),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private mountSimulator(simulator: ISimulatorHost) {
|
|
||||||
// TODO: 多设备 simulator 支持
|
|
||||||
this._simulator = simulator;
|
|
||||||
// TODO: emit simulator mounted
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: does needed?
|
// FIXME: does needed?
|
||||||
getComponent(componentName: string): any {
|
getComponent(componentName: string): any {
|
||||||
return this.simulator!.getComponent(componentName);
|
return this.simulator!.getComponent(componentName);
|
||||||
@ -498,17 +476,6 @@ export class DocumentModel {
|
|||||||
return this.rootNode;
|
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);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
setRendererReady(renderer: any) {
|
|
||||||
this.emitter.emit('lowcode_engine_renderer_ready', renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
acceptRootNodeVisitor(
|
acceptRootNodeVisitor(
|
||||||
visitorName: string = 'default',
|
visitorName: string = 'default',
|
||||||
visitorFn: (node: RootNode) => any ) {
|
visitorFn: (node: RootNode) => any ) {
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
import { Component } from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { observer } from '@ali/lowcode-editor-core';
|
|
||||||
import { DocumentModel } from './document-model';
|
|
||||||
import { BuiltinSimulatorHostView } from '../builtin-simulator';
|
|
||||||
|
|
||||||
@observer
|
|
||||||
export class DocumentView extends Component<{ document: DocumentModel }> {
|
|
||||||
shouldComponentUpdate() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const { document } = this.props;
|
|
||||||
const simulatorProps = document.simulatorProps;
|
|
||||||
const Simulator = document.designer.simulatorComponent || BuiltinSimulatorHostView;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classNames('lc-document', {
|
|
||||||
'lc-document-hidden': document.suspensed,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{/* 这一层将来做缩放用途 */}
|
|
||||||
<div className="lc-simulator-shell">
|
|
||||||
<Simulator {...simulatorProps} />
|
|
||||||
</div>
|
|
||||||
<DocumentInfoView document={document} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DocumentInfoView extends Component<{ document: DocumentModel }> {
|
|
||||||
render() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -533,6 +533,9 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
if (stage !== TransformStage.Clone) {
|
if (stage !== TransformStage.Clone) {
|
||||||
baseSchema.id = this.id;
|
baseSchema.id = this.id;
|
||||||
}
|
}
|
||||||
|
if (stage === TransformStage.Render) {
|
||||||
|
baseSchema.docId = this.document.id;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isLeaf()) {
|
if (this.isLeaf()) {
|
||||||
baseSchema.children = this.props.get('children')?.export(stage);
|
baseSchema.children = this.props.get('children')?.export(stage);
|
||||||
|
|||||||
@ -1,23 +1,22 @@
|
|||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
import { observer } from '@ali/lowcode-editor-core';
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
import { Designer } from '../designer';
|
import { Designer } from '../designer';
|
||||||
import { DocumentView } from '../document';
|
import { BuiltinSimulatorHostView } from '../builtin-simulator';
|
||||||
import { intl } from '../locale';
|
|
||||||
import './project.less';
|
import './project.less';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ProjectView extends Component<{ designer: Designer }> {
|
export class ProjectView extends Component<{ designer: Designer }> {
|
||||||
render() {
|
render() {
|
||||||
const { designer } = this.props;
|
const { designer } = this.props;
|
||||||
// TODO: support splitview
|
const project = designer.project;
|
||||||
const opens = designer.project.documents.filter((doc) => doc.opened);
|
const simulatorProps = project.simulatorProps;
|
||||||
|
const Simulator = designer.simulatorComponent || BuiltinSimulatorHostView;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="lc-project">
|
<div className="lc-project">
|
||||||
{opens.length > 0 ? (
|
<div className="lc-simulator-shell">
|
||||||
opens.map((doc) => <DocumentView key={doc.id} document={doc} />)
|
<Simulator {...simulatorProps} />
|
||||||
) : (
|
</div>
|
||||||
<div className="lc-project-empty">{intl('No opened document')}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { obx, computed } from '@ali/lowcode-editor-core';
|
|||||||
import { Designer } from '../designer';
|
import { Designer } from '../designer';
|
||||||
import { DocumentModel, isDocumentModel } from '../document';
|
import { DocumentModel, isDocumentModel } from '../document';
|
||||||
import { ProjectSchema, RootSchema } from '@ali/lowcode-types';
|
import { ProjectSchema, RootSchema } from '@ali/lowcode-types';
|
||||||
|
import { ISimulatorHost } from '../simulator';
|
||||||
|
|
||||||
export class Project {
|
export class Project {
|
||||||
private emitter = new EventEmitter();
|
private emitter = new EventEmitter();
|
||||||
@ -12,6 +13,15 @@ export class Project {
|
|||||||
|
|
||||||
@obx.ref canvasDisplayMode: 'exclusive' | 'overview' = 'exclusive';
|
@obx.ref canvasDisplayMode: 'exclusive' | 'overview' = 'exclusive';
|
||||||
|
|
||||||
|
private _simulator?: ISimulatorHost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟器
|
||||||
|
*/
|
||||||
|
get simulator(): ISimulatorHost | null {
|
||||||
|
return this._simulator || null;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 考虑项目级别 History
|
// TODO: 考虑项目级别 History
|
||||||
|
|
||||||
constructor(readonly designer: Designer, schema?: ProjectSchema) {
|
constructor(readonly designer: Designer, schema?: ProjectSchema) {
|
||||||
@ -102,7 +112,7 @@ export class Project {
|
|||||||
| string,
|
| string,
|
||||||
): any {}
|
): any {}
|
||||||
|
|
||||||
open(doc?: string | DocumentModel | RootSchema): void {
|
open(doc?: string | DocumentModel | RootSchema): DocumentModel | null {
|
||||||
if (!doc) {
|
if (!doc) {
|
||||||
const got = this.documents.find((item) => item.isBlank());
|
const got = this.documents.find((item) => item.isBlank());
|
||||||
if (got) {
|
if (got) {
|
||||||
@ -125,7 +135,7 @@ export class Project {
|
|||||||
return doc.open();
|
return doc.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDocumentModel(doc)) {
|
if (isDocumentModel(doc)) {
|
||||||
@ -154,6 +164,37 @@ export class Project {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供给模拟器的参数
|
||||||
|
*/
|
||||||
|
@computed get simulatorProps(): object {
|
||||||
|
let simulatorProps = this.designer.simulatorProps;
|
||||||
|
if (typeof simulatorProps === 'function') {
|
||||||
|
simulatorProps = simulatorProps(this);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...simulatorProps,
|
||||||
|
project: this,
|
||||||
|
onMount: this.mountSimulator.bind(this),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private mountSimulator(simulator: ISimulatorHost) {
|
||||||
|
// TODO: 多设备 simulator 支持
|
||||||
|
this._simulator = simulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRendererReady(renderer: any) {
|
||||||
|
this.emitter.emit('lowcode_engine_renderer_ready', renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRendererReady(fn: (args: any) => void): () => void {
|
||||||
|
this.emitter.on('lowcode_engine_renderer_ready', fn);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('lowcode_engine_renderer_ready', fn);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
onCurrentDocumentChange(fn: (doc: DocumentModel) => void): () => void {
|
onCurrentDocumentChange(fn: (doc: DocumentModel) => void): () => void {
|
||||||
this.emitter.on('current-document.change', fn);
|
this.emitter.on('current-document.change', fn);
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@ -154,6 +154,7 @@ export function isSimulatorHost(obj: any): obj is ISimulatorHost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeInstance<T = ComponentInstance> {
|
export interface NodeInstance<T = ComponentInstance> {
|
||||||
|
docId: string;
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
instance: T;
|
instance: T;
|
||||||
node?: Node | null;
|
node?: Node | null;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
class Monitor {
|
export class Monitor {
|
||||||
fn = (params: any) => {
|
fn = (params: any) => {
|
||||||
const { AES } = window as any;
|
const { AES } = window as any;
|
||||||
if (typeof AES.log === 'function') {
|
if (typeof AES.log === 'function') {
|
||||||
|
|||||||
@ -25,11 +25,9 @@ export const designer = new Designer({ editor: editor });
|
|||||||
editor.set(Designer, designer);
|
editor.set(Designer, designer);
|
||||||
editor.set('designer', designer);
|
editor.set('designer', designer);
|
||||||
|
|
||||||
designer.project.onCurrentDocumentChange((doc) => {
|
designer.project.onRendererReady(() => {
|
||||||
doc.onRendererReady(() => {
|
|
||||||
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
bus.emit(VE_EVENTS.VE_PAGE_PAGE_READY);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
interface Variable {
|
interface Variable {
|
||||||
type: 'variable';
|
type: 'variable';
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import LowCodeRenderer from '@ali/lowcode-react-renderer';
|
import LowCodeRenderer from '@ali/lowcode-react-renderer';
|
||||||
import { isObject } from 'lodash';
|
|
||||||
import { ReactInstance, Fragment, Component, createElement } from 'react';
|
import { ReactInstance, Fragment, Component, createElement } from 'react';
|
||||||
import { observer } from '@recore/obx-react';
|
import { observer } from '@recore/obx-react';
|
||||||
import { SimulatorRenderer } from './renderer';
|
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
|
||||||
import { host } from './host';
|
|
||||||
import './renderer.less';
|
import './renderer.less';
|
||||||
|
|
||||||
// patch cloneElement avoid lost keyProps
|
// patch cloneElement avoid lost keyProps
|
||||||
@ -36,12 +34,20 @@ const originCloneElement = window.React.cloneElement;
|
|||||||
return originCloneElement(child, props, ...rest);
|
return originCloneElement(child, props, ...rest);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class SimulatorRendererView extends Component<{ renderer: SimulatorRenderer }> {
|
export default class SimulatorRendererView extends Component<{ rendererContainer: SimulatorRendererContainer }> {
|
||||||
render() {
|
render() {
|
||||||
const { renderer } = this.props;
|
const { rendererContainer } = this.props;
|
||||||
return (
|
return (
|
||||||
<Layout renderer={renderer}>
|
<Layout rendererContainer={rendererContainer}>
|
||||||
<Renderer renderer={renderer} />
|
<Router onChange={(currentPath: string) => {
|
||||||
|
rendererContainer.redirect(currentPath);
|
||||||
|
}}>
|
||||||
|
{rendererContainer.getDocumentInstances().map((instance) => {
|
||||||
|
return <Route path={instance.document.get('fileName')}>
|
||||||
|
<Renderer documentInstance={instance} />
|
||||||
|
</Route>
|
||||||
|
})}
|
||||||
|
</Router>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -68,13 +74,13 @@ function getDeviceView(view: any, device: string, mode: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Layout extends Component<{ renderer: SimulatorRenderer }> {
|
class Layout extends Component<{ rendererContainer: SimulatorRendererContainer }> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { renderer, children } = this.props;
|
const { rendererContainer, children } = this.props;
|
||||||
const layout = renderer.layout;
|
const layout = rendererContainer.layout;
|
||||||
|
|
||||||
if (layout) {
|
if (layout) {
|
||||||
const { Component, props } = layout;
|
const { Component, props } = layout;
|
||||||
@ -86,26 +92,28 @@ class Layout extends Component<{ renderer: SimulatorRenderer }> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
class Renderer extends Component<{ documentInstance: DocumentInstance }> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { renderer } = this.props;
|
const { documentInstance } = this.props;
|
||||||
const { device, designMode } = renderer;
|
const { container } = documentInstance;
|
||||||
|
const { designMode, device } = container;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LowCodeRenderer
|
<LowCodeRenderer
|
||||||
schema={renderer.schema}
|
schema={documentInstance.schema}
|
||||||
components={renderer.components}
|
components={container.components}
|
||||||
appHelper={renderer.context}
|
appHelper={container.context}
|
||||||
// context={renderer.context}
|
// context={renderer.context}
|
||||||
designMode={designMode}
|
designMode={designMode}
|
||||||
suspended={renderer.suspended}
|
suspended={documentInstance.suspended}
|
||||||
self={renderer.scope}
|
self={documentInstance.scope}
|
||||||
customCreateElement={(Component: any, props: any, children: any) => {
|
customCreateElement={(Component: any, props: any, children: any) => {
|
||||||
const { __id, __desingMode, ...viewProps } = props;
|
const { __id, __desingMode, ...viewProps } = props;
|
||||||
viewProps.componentId = __id;
|
viewProps.componentId = __id;
|
||||||
const leaf = host.document.getNode(__id);
|
const leaf = documentInstance.getNode(__id);
|
||||||
viewProps._leaf = leaf;
|
viewProps._leaf = leaf;
|
||||||
viewProps._componentName = leaf?.componentName;
|
viewProps._componentName = leaf?.componentName;
|
||||||
let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children;
|
let _children = leaf?.isContainer() ? (children == null ? [] : Array.isArray(children) ? children : [children]) : children;
|
||||||
@ -158,7 +166,7 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
||||||
renderer.mountInstance(schema.id, ref);
|
documentInstance.mountInstance(schema.id, ref);
|
||||||
}}
|
}}
|
||||||
//onCompGetCtx={(schema: any, ctx: object) => {
|
//onCompGetCtx={(schema: any, ctx: object) => {
|
||||||
// renderer.mountContext(schema.id, ctx);
|
// renderer.mountContext(schema.id, ctx);
|
||||||
|
|||||||
@ -10,120 +10,47 @@ import { reactFindDOMNodes, FIBER_KEY } from './utils/react-find-dom-nodes';
|
|||||||
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
|
import { isESModule, isElement, cursor, setNativeSelection } from '@ali/lowcode-utils';
|
||||||
import { RootSchema, NpmInfo, ComponentSchema, TransformStage } from '@ali/lowcode-types';
|
import { RootSchema, NpmInfo, ComponentSchema, TransformStage } from '@ali/lowcode-types';
|
||||||
// just use types
|
// just use types
|
||||||
import { BuiltinSimulatorRenderer, NodeInstance, Component } from '@ali/lowcode-designer';
|
import { BuiltinSimulatorRenderer, NodeInstance, Component, DocumentModel, Node } from '@ali/lowcode-designer';
|
||||||
import Slot from './builtin-components/slot';
|
import Slot from './builtin-components/slot';
|
||||||
import Leaf from './builtin-components/leaf';
|
import Leaf from './builtin-components/leaf';
|
||||||
|
|
||||||
export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
export class DocumentInstance {
|
||||||
readonly isSimulatorRenderer = true;
|
private instancesMap = new Map<string, ReactInstance[]>();
|
||||||
private dispose?: () => void;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
if (!host) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dispose = host.connect(this, () => {
|
|
||||||
// sync layout config
|
|
||||||
|
|
||||||
// sync schema
|
|
||||||
this._schema = host.document.export(1);
|
|
||||||
|
|
||||||
// todo: split with others, not all should recompute
|
|
||||||
if (this._libraryMap !== host.libraryMap || this._componentsMap !== host.designer.componentsMap) {
|
|
||||||
this._libraryMap = host.libraryMap || {};
|
|
||||||
this._componentsMap = host.designer.componentsMap;
|
|
||||||
this.buildComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync designMode
|
|
||||||
this._designMode = host.designMode;
|
|
||||||
|
|
||||||
// sync suspended
|
|
||||||
|
|
||||||
// sync scope
|
|
||||||
|
|
||||||
// sync device
|
|
||||||
this._device = host.device;
|
|
||||||
});
|
|
||||||
host.componentsConsumer.consume(async (componentsAsset) => {
|
|
||||||
if (componentsAsset) {
|
|
||||||
await this.load(componentsAsset);
|
|
||||||
this.buildComponents();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
host.injectionConsumer.consume((data) => {
|
|
||||||
// sync utils, i18n, contants,... config
|
|
||||||
this._appContext = {
|
|
||||||
utils: {},
|
|
||||||
constants: {
|
|
||||||
name: 'demo',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get layout(): any {
|
|
||||||
// TODO: parse layout Component
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@obx.ref private _schema?: RootSchema;
|
@obx.ref private _schema?: RootSchema;
|
||||||
@computed get schema(): any {
|
@computed get schema(): any {
|
||||||
return this._schema;
|
return this._schema;
|
||||||
}
|
}
|
||||||
private _libraryMap: { [key: string]: string } = {};
|
|
||||||
private buildComponents() {
|
constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) {
|
||||||
this._components = buildComponents(this._libraryMap, this._componentsMap);
|
this.dispose = host.connect(this, () => {
|
||||||
}
|
// sync layout config
|
||||||
@obx.ref private _components: any = {};
|
|
||||||
@computed get components(): object {
|
// sync schema
|
||||||
// 根据 device 选择不同组件,进行响应式
|
this._schema = host.document.export(1);
|
||||||
// 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl
|
})
|
||||||
return this._components;
|
|
||||||
}
|
|
||||||
// context from: utils、constants、history、location、match
|
|
||||||
@obx.ref private _appContext = {};
|
|
||||||
@computed get context(): any {
|
|
||||||
return this._appContext;
|
|
||||||
}
|
|
||||||
@obx.ref private _designMode: string = 'design';
|
|
||||||
@computed get designMode(): any {
|
|
||||||
return this._designMode;
|
|
||||||
}
|
|
||||||
@obx.ref private _device: string = 'default';
|
|
||||||
@computed get device() {
|
|
||||||
return this._device;
|
|
||||||
}
|
|
||||||
@obx.ref private _componentsMap = {};
|
|
||||||
@computed get componentsMap(): any {
|
|
||||||
return this._componentsMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get suspended(): any {
|
@computed get suspended(): any {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@computed get scope(): any {
|
@computed get scope(): any {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 加载资源
|
|
||||||
*/
|
|
||||||
load(asset: Asset): Promise<any> {
|
|
||||||
return loader.load(asset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private instancesMap = new Map<string, ReactInstance[]>();
|
|
||||||
private unmountIntance(id: string, instance: ReactInstance) {
|
private unmountIntance(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);
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
instances.splice(i, 1);
|
instances.splice(i, 1);
|
||||||
host.setInstance(id, instances);
|
host.setInstance(this.document.id, id, instances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mountInstance(id: string, instance: ReactInstance | null) {
|
mountInstance(id: string, instance: ReactInstance | null) {
|
||||||
|
const docId = this.document.id;
|
||||||
const instancesMap = this.instancesMap;
|
const instancesMap = this.instancesMap;
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
let instances = this.instancesMap.get(id);
|
let instances = this.instancesMap.get(id);
|
||||||
@ -131,10 +58,10 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
instances = instances.filter(checkInstanceMounted);
|
instances = instances.filter(checkInstanceMounted);
|
||||||
if (instances.length > 0) {
|
if (instances.length > 0) {
|
||||||
instancesMap.set(id, instances);
|
instancesMap.set(id, instances);
|
||||||
host.setInstance(id, instances);
|
host.setInstance(this.document.id, id, instances);
|
||||||
} else {
|
} else {
|
||||||
instancesMap.delete(id);
|
instancesMap.delete(id);
|
||||||
host.setInstance(id, null);
|
host.setInstance(this.document.id, id, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -163,6 +90,7 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(instance as any)[SYMBOL_VNID] = id;
|
(instance as any)[SYMBOL_VNID] = id;
|
||||||
|
(instance as any)[SYMBOL_VDID] = docId;
|
||||||
let instances = this.instancesMap.get(id);
|
let instances = this.instancesMap.get(id);
|
||||||
if (instances) {
|
if (instances) {
|
||||||
const l = instances.length;
|
const l = instances.length;
|
||||||
@ -179,37 +107,11 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
instances = [instance];
|
instances = [instance];
|
||||||
}
|
}
|
||||||
instancesMap.set(id, instances);
|
instancesMap.set(id, instances);
|
||||||
host.setInstance(id, instances);
|
host.setInstance(this.document.id, id, instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ctxMap = new Map<string, object>();
|
mountContext(docId: string, id: string, ctx: object) {
|
||||||
mountContext(id: string, ctx: object) {
|
// this.ctxMap.set(id, ctx);
|
||||||
this.ctxMap.set(id, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponent(componentName: string) {
|
|
||||||
const paths = componentName.split('.');
|
|
||||||
const subs: string[] = [];
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const component = this._components[componentName];
|
|
||||||
if (component) {
|
|
||||||
return getSubComponent(component, subs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sub = paths.pop();
|
|
||||||
if (!sub) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
subs.unshift(sub);
|
|
||||||
componentName = paths.join('.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponentInstances(id: string): ReactInstance[] | null {
|
|
||||||
return this.instancesMap.get(id) || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponent(schema: ComponentSchema): Component | null {
|
createComponent(schema: ComponentSchema): Component | null {
|
||||||
@ -245,18 +147,18 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
if (schema.children && schema.children.length > 0) {
|
if (schema.children && schema.children.length > 0) {
|
||||||
children = schema.children.map((item: any) => getElement(componentsMap, item, propsMap));
|
children = schema.children.map((item: any) => getElement(componentsMap, item, propsMap));
|
||||||
}
|
}
|
||||||
const _leaf = host.document.designer.currentDocument?.createNode(schema);
|
const _leaf = this.document.designer.currentDocument?.createNode(schema);
|
||||||
const node = host.document.createNode(schema);
|
const node = this.document.createNode(schema);
|
||||||
let props = processPropsSchema(schema.props, propsMap);
|
let props = processPropsSchema(schema.props, propsMap);
|
||||||
props = host.document.designer.transformProps(props, node, TransformStage.Init);
|
props = this.document.designer.transformProps(props, node, TransformStage.Init);
|
||||||
props = host.document.designer.transformProps(props, node, TransformStage.Render);
|
props = this.document.designer.transformProps(props, node, TransformStage.Render);
|
||||||
return createElement(Com, {...props, _leaf}, children);
|
return createElement(Com, {...props, _leaf}, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderer = this;
|
const container = this.container;
|
||||||
class Com extends React.Component {
|
class Com extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const componentsMap = renderer.componentsMap;
|
const componentsMap = container.componentsMap;
|
||||||
let children = null;
|
let children = null;
|
||||||
if (_schema.children && Array.isArray(_schema.children)) {
|
if (_schema.children && Array.isArray(_schema.children)) {
|
||||||
children = _schema.children?.map((item:any) => getElement(componentsMap, item, this.props));
|
children = _schema.children?.map((item:any) => getElement(componentsMap, item, this.props));
|
||||||
@ -268,6 +170,119 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
return Com;
|
return Com;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNode(id: string): Node | null {
|
||||||
|
return this.document.getNode(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
||||||
|
readonly isSimulatorRenderer = true;
|
||||||
|
private dispose?: () => void;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
if (!host) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispose = host.connect(this, () => {
|
||||||
|
// sync layout config
|
||||||
|
// todo: split with others, not all should recompute
|
||||||
|
if (this._libraryMap !== host.libraryMap || this._componentsMap !== host.designer.componentsMap) {
|
||||||
|
this._libraryMap = host.libraryMap || {};
|
||||||
|
this._componentsMap = host.designer.componentsMap;
|
||||||
|
this.buildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// sync designMode
|
||||||
|
this._designMode = host.designMode;
|
||||||
|
|
||||||
|
// sync device
|
||||||
|
this._device = host.device;
|
||||||
|
});
|
||||||
|
host.componentsConsumer.consume(async (componentsAsset) => {
|
||||||
|
if (componentsAsset) {
|
||||||
|
await this.load(componentsAsset);
|
||||||
|
this.buildComponents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
host.injectionConsumer.consume((data) => {
|
||||||
|
// sync utils, i18n, contants,... config
|
||||||
|
this._appContext = {
|
||||||
|
utils: {},
|
||||||
|
constants: {
|
||||||
|
name: 'demo',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get layout(): any {
|
||||||
|
// TODO: parse layout Component
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _libraryMap: { [key: string]: string } = {};
|
||||||
|
private buildComponents() {
|
||||||
|
this._components = buildComponents(this._libraryMap, this._componentsMap);
|
||||||
|
}
|
||||||
|
@obx.ref private _components: any = {};
|
||||||
|
@computed get components(): object {
|
||||||
|
// 根据 device 选择不同组件,进行响应式
|
||||||
|
// 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl
|
||||||
|
return this._components;
|
||||||
|
}
|
||||||
|
// context from: utils、constants、history、location、match
|
||||||
|
@obx.ref private _appContext = {};
|
||||||
|
@computed get context(): any {
|
||||||
|
return this._appContext;
|
||||||
|
}
|
||||||
|
@obx.ref private _designMode: string = 'design';
|
||||||
|
@computed get designMode(): any {
|
||||||
|
return this._designMode;
|
||||||
|
}
|
||||||
|
@obx.ref private _device: string = 'default';
|
||||||
|
@computed get device() {
|
||||||
|
return this._device;
|
||||||
|
}
|
||||||
|
@obx.ref private _componentsMap = {};
|
||||||
|
@computed get componentsMap(): any {
|
||||||
|
return this._componentsMap;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 加载资源
|
||||||
|
*/
|
||||||
|
load(asset: Asset): Promise<any> {
|
||||||
|
return loader.load(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private documentInstanceMap = new Map<string, DocumentInstance>();
|
||||||
|
|
||||||
|
|
||||||
|
redirect(path: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getComponent(componentName: string) {
|
||||||
|
const paths = componentName.split('.');
|
||||||
|
const subs: string[] = [];
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const component = this._components[componentName];
|
||||||
|
if (component) {
|
||||||
|
return getSubComponent(component, subs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sub = paths.pop();
|
||||||
|
if (!sub) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
subs.unshift(sub);
|
||||||
|
componentName = paths.join('.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
getClosestNodeInstance(from: ReactInstance, nodeId?: string): NodeInstance<ReactInstance> | null {
|
getClosestNodeInstance(from: ReactInstance, nodeId?: string): NodeInstance<ReactInstance> | null {
|
||||||
return getClosestNodeInstance(from, nodeId);
|
return getClosestNodeInstance(from, nodeId);
|
||||||
}
|
}
|
||||||
@ -310,8 +325,8 @@ export class SimulatorRenderer implements BuiltinSimulatorRenderer {
|
|||||||
document.documentElement.classList.add('engine-page');
|
document.documentElement.classList.add('engine-page');
|
||||||
document.body.classList.add('engine-document'); // important! Stylesheet.invoke depends
|
document.body.classList.add('engine-document'); // important! Stylesheet.invoke depends
|
||||||
|
|
||||||
reactRender(createElement(SimulatorRendererView, { renderer: this }), container);
|
reactRender(createElement(SimulatorRendererView, { rendererContainer: this }), container);
|
||||||
host.document.setRendererReady(this);
|
host.project.setRendererReady(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,6 +432,7 @@ function cacheReactKey(el: Element): Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SYMBOL_VNID = Symbol('_LCNodeId');
|
const SYMBOL_VNID = Symbol('_LCNodeId');
|
||||||
|
const SYMBOL_VDID = Symbol('_LCDocId');
|
||||||
|
|
||||||
function getClosestNodeInstance(from: ReactInstance, specId?: string): NodeInstance<ReactInstance> | null {
|
function getClosestNodeInstance(from: ReactInstance, specId?: string): NodeInstance<ReactInstance> | null {
|
||||||
let el: any = from;
|
let el: any = from;
|
||||||
@ -430,9 +446,11 @@ function getClosestNodeInstance(from: ReactInstance, specId?: string): NodeInsta
|
|||||||
while (el) {
|
while (el) {
|
||||||
if (SYMBOL_VNID in el) {
|
if (SYMBOL_VNID in el) {
|
||||||
const nodeId = el[SYMBOL_VNID];
|
const nodeId = el[SYMBOL_VNID];
|
||||||
|
const docId = el[SYMBOL_VDID];
|
||||||
if (!specId || specId === nodeId) {
|
if (!specId || specId === nodeId) {
|
||||||
return {
|
return {
|
||||||
nodeId: nodeId,
|
docId,
|
||||||
|
nodeId,
|
||||||
instance: el,
|
instance: el,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -450,9 +468,11 @@ function getNodeInstance(fiberNode: any, specId?: string): NodeInstance<ReactIns
|
|||||||
const instance = fiberNode.stateNode;
|
const instance = fiberNode.stateNode;
|
||||||
if (instance && SYMBOL_VNID in instance) {
|
if (instance && SYMBOL_VNID in instance) {
|
||||||
const nodeId = instance[SYMBOL_VNID];
|
const nodeId = instance[SYMBOL_VNID];
|
||||||
|
const docId = instance[SYMBOL_VDID];
|
||||||
if (!specId || specId === nodeId) {
|
if (!specId || specId === nodeId) {
|
||||||
return {
|
return {
|
||||||
nodeId: nodeId,
|
docId,
|
||||||
|
nodeId,
|
||||||
instance: instance,
|
instance: instance,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -467,4 +487,4 @@ function checkInstanceMounted(instance: any): boolean {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new SimulatorRenderer();
|
export default new SimulatorRendererContainer();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user