From b0aeed3620e734fd1e48d9389ef55e1d7089f3d0 Mon Sep 17 00:00:00 2001 From: "wuyue.xht" Date: Tue, 24 Nov 2020 19:38:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E4=BD=8E=E4=BB=A3=E7=A0=81=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rax-renderer/src/engine/compEngine.tsx | 31 +++ .../rax-simulator-renderer/src/renderer.ts | 209 ++++++++++-------- 2 files changed, 153 insertions(+), 87 deletions(-) diff --git a/packages/rax-renderer/src/engine/compEngine.tsx b/packages/rax-renderer/src/engine/compEngine.tsx index 4e17fc0b8..3e3320d26 100644 --- a/packages/rax-renderer/src/engine/compEngine.tsx +++ b/packages/rax-renderer/src/engine/compEngine.tsx @@ -6,6 +6,7 @@ import Debug from 'debug'; import classnames from 'classnames'; import { isSchema, getFileCssName } from '../utils'; import BaseEngine from './base'; +import AppContext from '../context/appContext'; const debug = Debug('engine:comp'); @@ -66,6 +67,35 @@ export default class CompEngine extends BaseEngine { debug(`comp.componentDidCatch - ${this.props.__schema.fileName}`); } + __createContextDom = (childCtx, currCtx, props) => ( + + {(context) => { + this.context = context; + this.__generateCtx(currCtx); + this.__render(); + return ( + + {context.engine.createElement( + props.__components.Component, + { + ...props, + ref: this.__getRef, + className: classnames(getFileCssName(props.__schema.fileName), props.className), + __id: props.__schema.id, + }, + this.__createDom(), + )} + + ); + }} + + ); + render() { const { __schema } = this.props; @@ -106,6 +136,7 @@ export default class CompEngine extends BaseEngine { { component: this, }, + this.props, )} ); diff --git a/packages/rax-simulator-renderer/src/renderer.ts b/packages/rax-simulator-renderer/src/renderer.ts index 80441d474..0ba0d70b7 100644 --- a/packages/rax-simulator-renderer/src/renderer.ts +++ b/packages/rax-simulator-renderer/src/renderer.ts @@ -1,12 +1,12 @@ import { BuiltinSimulatorRenderer, Component, DocumentModel, Node, NodeInstance } from '@ali/lowcode-designer'; -import { ComponentSchema, NodeSchema, NpmInfo, RootSchema } from '@ali/lowcode-types'; +import { ComponentSchema, NodeSchema, NpmInfo, RootSchema, TransformStage } from '@ali/lowcode-types'; import { Asset, cursor, isElement, isESModule, isReactComponent, setNativeSelection } from '@ali/lowcode-utils'; import { computed, obx } from '@recore/obx'; import DriverUniversal from 'driver-universal'; import { EventEmitter } from 'events'; import { createMemoryHistory, MemoryHistory } from 'history'; // @ts-ignore -import { ComponentType, createElement, render as raxRender, shared } from 'rax'; +import Rax, { ComponentType, createElement, render as raxRender, shared } from 'rax'; import Leaf from './builtin-components/leaf'; import Slot from './builtin-components/slot'; import { host } from './host'; @@ -25,6 +25,8 @@ export interface LibraryMap { const SYMBOL_VNID = Symbol('_LCNodeId'); const SYMBOL_VDID = Symbol('_LCDocId'); +const INTERNAL = '_internal'; + function accessLibrary(library: string | object) { if (typeof library !== 'string') { return library; @@ -410,7 +412,9 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { } instance = Instance.get(dom); while (instance && instance[INTERNAL]) { - if (isValidDesignModeRaxComponentInstance(instance)) { + // 剔除低代码组件的内部组件 + if (isValidDesignModeRaxComponentInstance(instance) && !findComponentCreator(instance)) { + // if (instance && SYMBOL_VNID in instance) { // const docId = (instance.props as any).schema.docId; return { docId: instance.props._leaf.document.id, @@ -489,97 +493,31 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { }; } - createComponent(schema: ComponentSchema): Component | null { - return null; - // TODO: use ComponentEngine refactor - /* - const _schema = { + createComponent(schema: NodeSchema): Component | null { + const _schema: any = { ...schema, }; _schema.methods = {}; _schema.lifeCycles = {}; - const node = host.document.createNode(_schema); - _schema = node.export(TransformStage.Render); - - const processPropsSchema = (propsSchema: any, propsMap: any): any => { - if (!propsSchema) { - return {}; - } - - const result = { ...propsSchema }; - const reg = /^(?:this\.props|props)\.(\S+)$/; - Object.keys(result).map((key: string) => { - if (result[key]?.type === 'JSExpression') { - const { value } = result[key]; - const matched = reg.exec(value); - if (matched) { - const propName = matched[1]; - result[key] = propsMap[propName]; - } - } else if (result[key]?.type === 'JSSlot') { - const schema = result[key].value; - result[key] = createElement(Ele, {schema, propsMap: {}}); - } - }); - - return result; - }; - - const renderer = this; - const componentsMap = renderer.componentsMap; - - class Ele extends React.Component<{ schema: any, propsMap: any }> { - private isModal: boolean; - - constructor(props: any){ - super(props); - const componentMeta = host.document.getComponentMeta(props.schema.componentName); - if (componentMeta?.prototype?.isModal()) { - this.isModal = true; - return; - } - } - - render() { - if (this.isModal) { - return null; - } - const { schema, propsMap } = this.props; - const Com = componentsMap[schema.componentName]; - if (!Com) { - return null; - } - let children = null; - if (schema.children && schema.children.length > 0) { - children = schema.children.map((item: any) => createElement(Ele, {schema: item, propsMap})); - } - const props = processPropsSchema(schema.props, propsMap); - const _leaf = host.document.createNode(schema); - - return createElement(Com, {...props, _leaf}, children); - } - const _leaf = this.document.designer.currentDocument?.createNode(schema); - const node = this.document.createNode(schema); - let props = processPropsSchema(schema.props, propsMap); - props = this.document.designer.transformProps(props, node, TransformStage.Init); - props = this.document.designer.transformProps(props, node, TransformStage.Render); - return createElement(Com, { ...props, _leaf }, children); - }; - - const container = this; - class Com extends React.Component { - render() { - const componentsMap = container.componentsMap; - let children = null; - if (_schema.children && Array.isArray(_schema.children)) { - children = _schema.children?.map((item: any) => getElement(componentsMap, item, this.props)); - } - } + if (schema.componentName === 'Component' && (schema as ComponentSchema).css) { + const doc = window.document; + const s = doc.createElement('style'); + s.setAttribute('type', 'text/css'); + s.setAttribute('id', `Component-${schema.id || ''}`); + s.appendChild(doc.createTextNode((schema as ComponentSchema).css || '')); + doc.getElementsByTagName('head')[0].appendChild(s); } - return Com; - */ + // const node = host.currentDocument?.createNode(_schema); + // _schema = node?.export(TransformStage.Render) || {}; + + + + const renderer = this; + const { componentsMap } = renderer; + + return getComponentController(schema, componentsMap); } private _running = false; @@ -661,4 +599,101 @@ function findComponent(libraryMap: LibraryMap, componentName: string, npm?: NpmI return getSubComponent(library, paths); } +const processPropsSchema = (propsSchema: any, propsMap: any, componentsMap: any): any => { + if (!propsSchema) { + return {}; + } + + const result = { ...propsSchema }; + const reg = /^(?:this\.props|props)\.(\S+)$/; + Object.keys(result).map((key: string) => { + if (result[key]?.type === 'JSExpression') { + const { value } = result[key]; + const matched = reg.exec(value); + if (matched) { + const propName = matched[1]; + result[key] = propsMap[propName]; + } + } else if (result[key]?.type === 'JSSlot') { + const schema = result[key].value; + result[key] = createElement(ComponentCreator, { schema, propsMap: {}, componentsMap }); + } + }); + + return result; +}; + +function findComponentCreator(instance: any) { + let isComponentCreator = false; + while (instance && !isComponentCreator) { + instance = instance[INTERNAL]?.__parentInstance; + isComponentCreator = instance instanceof ComponentCreator; + } + return isComponentCreator; +} + +class ComponentCreator extends Rax.Component<{ schema: any; propsMap: any, componentsMap: any }> { + private isModal: boolean; + + constructor(props: any) { + super(props); + const componentMeta = host.currentDocument?.getComponentMeta(props.schema.componentName); + if (componentMeta?.prototype?.isModal()) { + this.isModal = true; + } + } + + render() { + if (this.isModal) { + return null; + } + const { schema, propsMap, componentsMap } = this.props; + const ComponentClass = componentsMap[schema.componentName]; + if (!ComponentClass) { + return null; + } + let children = null; + if (schema.children && schema.children.length > 0) { + children = schema.children.map((item: any, index: number) => createElement(ComponentCreator, { schema: item, propsMap, componentsMap, key: item?.id || index })); + } + const props = processPropsSchema(schema.props, propsMap, componentsMap); + const _leaf = host.currentDocument?.createNode(schema); + + return createElement(ComponentClass, { ...props, _leaf }, children); + } +} + +function getComponentController(schema: NodeSchema, componentsMap: any) { + class ComponentController extends Rax.Component<{ schema: any }> { + renderSchema: any; + + constructor(props: any) { + super(props); + const node = host.currentDocument?.createNode(schema); + this.renderSchema = node?.export(TransformStage.Render) || {}; + } + + // TODO: 暂时解决性能问题 + shouldComponentUpdate() { + return false; + } + + render() { + const { renderSchema } = this; + const { componentName } = renderSchema; + if (componentName === 'Component') { + let children = [] as any; + const propsMap = this.props || {}; + if (renderSchema.children && Array.isArray(renderSchema.children)) { + children = renderSchema.children.map((item: any, index: number) => createElement(ComponentCreator, { schema: item, propsMap, componentsMap, key: item?.id || index })); + } + return createElement('div', {}, children); + } else { + return createElement(ComponentCreator, { schema, propsMap: {}, componentsMap }); + } + } + } + return ComponentController; +} + export default new SimulatorRendererContainer();