debug start

This commit is contained in:
kangwei 2020-02-18 05:14:12 +08:00
parent a127fc8d5f
commit 5f0ac69595
13 changed files with 127 additions and 74 deletions

View File

@ -1,7 +1,7 @@
// NOTE: 仅用作类型标注,切勿作为实体使用
import { SimulatorRenderer } from '../renderer/renderer';
import { SimulatorHost } from './host';
import { AssetLevel, AssetList, isAssetBundle, isAssetItem, isCSSUrl, AssetType, assetItem } from '../utils/asset';
import { AssetLevel, AssetLevels, AssetList, isAssetBundle, isAssetItem, isCSSUrl, AssetType, assetItem } from '../utils/asset';
export function createSimulator(host: SimulatorHost, iframe: HTMLIFrameElement, vendors: AssetList = []): Promise<SimulatorRenderer> {
const win: any = iframe.contentWindow;
@ -11,10 +11,9 @@ export function createSimulator(host: SimulatorHost, iframe: HTMLIFrameElement,
const styles: any = {};
const scripts: any = {};
Object.keys(AssetLevel).forEach((key) => {
const v = (AssetLevel as any)[key];
styles[v] = [];
scripts[v] = [];
AssetLevels.forEach((lv) => {
styles[lv] = [];
scripts[lv] = [];
});
function parseAssetList(assets: AssetList, level?: AssetLevel) {
@ -37,13 +36,13 @@ export function createSimulator(host: SimulatorHost, iframe: HTMLIFrameElement,
}
const id = asset.id ? ` data-id="${asset.id}"` : '';
const lv = asset.level || level || AssetLevel.BaseDepends;
if (asset.type === 'jsUrl') {
if (asset.type === AssetType.JSUrl) {
(scripts[lv] || scripts[AssetLevel.App]).push(`<script src="${asset.content}"${id}></script>`)
} else if (asset.type === 'jsText') {
} else if (asset.type === AssetType.JSText) {
(scripts[lv] || scripts[AssetLevel.App]).push(`<script${id}>${asset.content}</script>`);
} else if (asset.type === 'cssUrl') {
} else if (asset.type === AssetType.CSSUrl) {
(styles[lv] || styles[AssetLevel.App]).push(`<link rel="stylesheet" href="${asset.content}"${id} />`);
} else if (asset.type === 'cssText') {
} else if (asset.type === AssetType.CSSText) {
(styles[lv] || styles[AssetLevel.App]).push(`<style type="text/css"${id}>${asset.content}</style>`);
}
}
@ -53,10 +52,10 @@ export function createSimulator(host: SimulatorHost, iframe: HTMLIFrameElement,
const styleFrags = Object.keys(styles).map(key => {
return styles[key].join('\n') + `<meta level="${key}" />`;
});
}).join('');
const scriptFrags = Object.keys(scripts).map(key => {
return styles[key].join('\n') + `<meta level="${key}" />`;
});
return scripts[key].join('\n');
}).join('');
doc.open();
doc.write(`<!doctype html><html><head><meta charset="utf-8"/>

View File

@ -25,6 +25,7 @@ export class SimulatorHostView extends Component<SimulatorProps & {
super(props);
const { documentContext } = this.props;
this.host = (documentContext.simulator as SimulatorHost) || new SimulatorHost(documentContext);
this.host.setProps(this.props);
}
shouldComponentUpdate(nextProps: SimulatorProps) {
this.host.setProps(nextProps);

View File

@ -6,7 +6,7 @@ import { SimulatorRenderer } from '../renderer/renderer';
import Node, { NodeParent } from '../../../designer/document/node/node';
import DocumentModel from '../../../designer/document/document-model';
import ResourceConsumer from './resource-consumer';
import { AssetLevel, Asset, assetBundle } from '../utils/asset';
import { AssetLevel, Asset, assetBundle, assetItem, AssetType } from '../utils/asset';
import { DragObjectType, isShaken, LocateEvent, DragNodeObject, DragNodeDataObject } from '../../../designer/dragon';
import { LocationData } from '../../../designer/location';
import { NodeData } from '../../../designer/schema';
@ -32,23 +32,19 @@ const defaultSimulatorUrl = (() => {
if (process.env.NODE_ENV === 'production') {
urls = [`${publicPath}simulator-renderer.min.css`, `${publicPath}simulator-renderer.min.js`];
} else {
urls = [`${publicPath}simulator-renderer.js`];
urls = [`${publicPath}simulator-renderer.css`, `${publicPath}simulator-renderer.js`];
}
return urls;
})();
const defaultDepends = [
{
type: 'jsUrl',
content:
'https://g.alicdn.com/mylib/??react/16.11.0/umd/react.production.min.js,react-dom/16.8.6/umd/react-dom.production.min.js,prop-types/15.7.2/prop-types.min.js',
id: 'rect',
},
{
type: 'jsText',
content:
'React.PropTypes=window.PropTypes;window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;',
},
// https://g.alicdn.com/mylib/??react/16.11.0/umd/react.production.min.js,react-dom/16.8.6/umd/react-dom.production.min.js,prop-types/15.7.2/prop-types.min.js
assetItem(AssetType.JSText, 'window.React=parent.React;window.ReactDOM=parent.ReactDOM;', undefined, 'react'),
assetItem(
AssetType.JSText,
'window.PropTypes=parent.PropTypes;React.PropTypes=parent.PropTypes; window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;',
),
assetItem(AssetType.JSUrl, 'http://localhost:4444/js/index.js'),
];
export class SimulatorHost implements ISimulator<SimulatorProps> {
@ -138,15 +134,7 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
return this._renderer;
}
readonly componentsConsumer = new ResourceConsumer<{
componentsAsset?: Asset;
componentsMap: object;
}>(() => {
return {
componentsAsset: this.componentsAsset,
componentsMap: this.componentsMap,
};
});
readonly componentsConsumer = new ResourceConsumer<Asset | undefined>(() => this.componentsAsset);
readonly injectionConsumer = new ResourceConsumer(() => {
return {};
@ -350,8 +338,8 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
throw new Error('Method not implemented.');
}
getClosestNodeId(elem: Element): string {
throw new Error('Method not implemented.');
getClosestNodeId(elem: Element): string | null {
return this.renderer?.getClosestNodeId(elem) || null;
}
findDOMNodes(instance: ComponentInstance): (Element | Text)[] | null {

View File

@ -58,7 +58,11 @@ export default class ResourceConsumer<T = any> {
}
await consumer(this._data);
// TODO: catch error and report
this.emitter.emit('consume');
if (this.resovleFirst) {
this.resovleFirst();
} else {
this._firstConsumed = true;
}
});
}
@ -72,9 +76,15 @@ export default class ResourceConsumer<T = any> {
this.emitter.removeAllListeners();
}
private _firstConsumed: boolean = false;
private resovleFirst?: () => void;
waitFirstConsume(): Promise<any> {
if (this._firstConsumed) {
return Promise.resolve();
}
return new Promise((resolve) => {
this.emitter.once('consume', resolve);
this.resovleFirst = resolve;
});
}
}

View File

@ -1,4 +1,4 @@
// import { Engine as LowCodeRenderer } from '@ali/iceluna-sdk';
import LowCodeRenderer from '@ali/iceluna-sdk';
import { ReactInstance, Fragment, Component } from 'react';
import { observer } from '@recore/core-obx';
import { SimulatorRenderer } from './renderer';
@ -50,20 +50,21 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
componentsMap={renderer.componentsMap}
suspended={renderer.suspended}
self={renderer.scope}
onComponentGetRef={(schema: any, ref: ReactInstance | null) => {
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
renderer.mountInstance(schema.id, ref);
}}
onComponentGetCtx={(schema: any, ctx: object) => {
renderer.mountContext(schema.id, ctx);
}}
//onCompGetCtx={(schema: any, ctx: object) => {
// renderer.mountContext(schema.id, ctx);
//}}
/>
);
}
}
/*
class LowCodeRenderer extends Component<any> {
render() {
const { schema } = this.props;
return <div>{JSON.stringify(this.props.schema)}</div>
}
}
}*/

View File

@ -67,6 +67,9 @@ export class SimulatorRenderer {
// sync schema
this._schema = host.document.schema;
this._componentsMap = host.designer.componentsMap;
this.buildComponents();
// sync designMode
// sync suspended
@ -75,13 +78,11 @@ export class SimulatorRenderer {
// sync device
});
host.componentsConsumer.consume(async (data) => {
if (data.componentsAsset) {
await this.load(data.componentsAsset);
host.componentsConsumer.consume(async (componentsAsset) => {
if (componentsAsset) {
await this.load(componentsAsset);
this.buildComponents();
}
// sync componetsMap
this._componentsMap = data.componentsMap;
});
host.injectionConsumer.consume((data) => {
// sync utils, i18n, contants,... config
@ -103,11 +104,14 @@ export class SimulatorRenderer {
@computed get schema(): any {
return this._schema;
}
@obx.ref private _componentsMap = {};
private buildComponents() {
this._components = buildComponents(this._componentsMap);
}
@obx.ref private _components = {};
@computed get components(): object {
// 根据 device 选择不同组件,进行响应式
// 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl
return buildComponents(this._componentsMap);
return this._components;
}
// context from: utils、constants、history、location、match
@obx.ref private _appContext = {};
@ -118,6 +122,7 @@ export class SimulatorRenderer {
@computed get designMode(): any {
return 'border';
}
@obx.ref private _componentsMap = {};
@computed get componentsMap(): any {
return this._componentsMap;
}

View File

@ -20,6 +20,15 @@ export enum AssetLevel {
App = 6,
}
export const AssetLevels = [
AssetLevel.BaseDepends,
AssetLevel.BaseComponents,
AssetLevel.Theme,
AssetLevel.Runtime,
AssetLevel.Components,
AssetLevel.App,
];
export type URL = string;
export enum AssetType {
@ -27,7 +36,7 @@ export enum AssetType {
CSSUrl = 'cssUrl',
CSSText = 'cssText',
JSText = 'jsText',
Bundle = 'bundel',
Bundle = 'bundle',
}
export interface AssetBundle {
@ -64,7 +73,7 @@ export function assetBundle(assets?: Asset | AssetList | null, level?: AssetLeve
}
export function assetItem(type: AssetType, content?: string | null, level?: AssetLevel, id?: string): AssetItem | null {
if (content) {
if (!content) {
return null;
}
return {

View File

@ -1,6 +1,6 @@
import { load, evaluate } from './script';
import StylePoint from './style';
import { Asset, AssetLevel, AssetType, AssetList, isAssetBundle, isAssetItem, assetItem, isCSSUrl, AssetItem } from './asset';
import { Asset, AssetLevel, AssetLevels, AssetType, AssetList, isAssetBundle, isAssetItem, assetItem, isCSSUrl, AssetItem } from './asset';
function parseAssetList(scripts: any, styles: any, assets: AssetList, level?: AssetLevel) {
for (let asset of assets) {
@ -50,10 +50,9 @@ export class AssetLoader {
async load(asset: Asset) {
const styles: any = {};
const scripts: any = {};
Object.keys(AssetLevel).forEach((key) => {
const v = (AssetLevel as any)[key];
styles[v] = [];
scripts[v] = [];
AssetLevels.forEach((lv) => {
styles[lv] = [];
scripts[lv] = [];
});
parseAsset(scripts, styles, asset);
const styleQueue: AssetItem[] = styles[AssetLevel.BaseDepends].concat(

View File

@ -0,0 +1,28 @@
.lc-designer {
position: relative;
min-width: 500px;
min-height: 500px;
.lc-project {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
.lc-document {
width: 100%;
height: 100%;
&&-hidden {
// todo:
display: none;
}
.lc-simulator-shell {
width: 100%;
height: 100%;
}
}
}
}

View File

@ -93,7 +93,7 @@ export default class Node {
this._directives = new Props(this, {});
Object.keys(extras).forEach(key => {
if (DIRECTIVES.indexOf(key) > -1) {
this.directives!.add((extras as any)[key], key);
this._directives!.add((extras as any)[key], key);
delete (extras as any)[key];
}
});
@ -295,9 +295,9 @@ export default class Node {
// TODO...
const schema: any = {
componentName: this.componentName,
...this.extras,
props: this.props,
...this.directives,
...this.extras?.value,
props: this.props?.value || {},
...this.directives?.value,
};
if (serialize) {
schema.id = this.id;

View File

@ -65,9 +65,10 @@ export default class Props<O = any> implements IPropParent {
constructor(readonly owner: O, value?: PropsMap | PropsList | null) {
if (Array.isArray(value)) {
this.type = 'list';
value.forEach(item => {});
this.items = value.map(item => new Prop(this, item.value, item.name, item.spread));
} else if (value != null) {
this.type = 'map';
this.items = Object.keys(value).map(key => new Prop(this, value[key], key));
}
}

View File

@ -35,12 +35,24 @@ import Props from './props/props';
*/
export default class RootNode extends Node implements NodeParent {
readonly isRootNode = true;
readonly isNodeParent = true;
readonly index = 0;
readonly nextSibling = null;
readonly prevSibling = null;
readonly zLevel = 0;
readonly parent = null;
get isNodeParent() {
return true;
}
get index() {
return 0;
}
get nextSibling() {
return null
}
get prevSibling() {
return null
}
get zLevel() {
return 0;
}
get parent() {
return null
}
get children(): NodeChildren {
return this._children as NodeChildren;
}
@ -51,7 +63,7 @@ export default class RootNode extends Node implements NodeParent {
return this._extras as any;
}
get directives(): Props<RootNode> {
return this._props as any;
return this._directives as any;
}
internalSetParent(parent: null) {}

View File

@ -132,9 +132,9 @@ export interface ISimulator<P = object> extends ISensor {
/**
*
*/
getComponentContext(node: Node): object;
getComponentContext(node: Node): object | null;
getClosestNodeId(elem: Element): string;
getClosestNodeId(elem: Element): string | null;
findDOMNodes(instance: ComponentInstance): Array<Element | Text> | null;