diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index 79a466e97..81334e96c 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -16,9 +16,8 @@ import { isPlainObject, AssetLoader, getProjectUtils, - applyActivities, } from '@ali/lowcode-utils'; -import { RootSchema, ComponentSchema, TransformStage, NodeSchema, ActivityType, ActivityData } from '@ali/lowcode-types'; +import { ComponentSchema, TransformStage, NodeSchema } from '@ali/lowcode-types'; // just use types import { BuiltinSimulatorRenderer, NodeInstance, Component, DocumentModel, Node } from '@ali/lowcode-designer'; import LowCodeRenderer from '@ali/lowcode-react-renderer'; @@ -28,8 +27,6 @@ import Leaf from './builtin-components/leaf'; import { withQueryParams, parseQuery } from './utils/url'; const loader = new AssetLoader(); -const DELAY_THRESHOLD = 10; -const FULL_RENDER_THRESHOLD = 500; configure({ enforceActions: 'never' }); export class DocumentInstance { @@ -447,16 +444,11 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { class LowCodeComp extends React.Component { render() { - const newSchema = host.designer.transformProps(_schema as any, { - componentMeta: { - prototype: 'lowcodeComp', - }, - isRoot: () => false, - } as Node, TransformStage.Render); const extraProps = getLowCodeComponentProps(this.props); return createElement(LowCodeRenderer, { ...extraProps, // 防止覆盖下面内置属性 - schema: newSchema, + // 使用 _schema 为了使低代码组件在页面设计中使用变量,同 react 组件使用效果一致 + schema: _schema, components: renderer.components, designMode: renderer.designMode, device: renderer.device, diff --git a/packages/renderer-core/src/hoc/leaf.tsx b/packages/renderer-core/src/hoc/leaf.tsx index c309e6e84..f40522a58 100644 --- a/packages/renderer-core/src/hoc/leaf.tsx +++ b/packages/renderer-core/src/hoc/leaf.tsx @@ -26,7 +26,6 @@ export type IComponentHoc = { }; export type IComponentConstruct = (Comp: types.IBaseRenderer, info: IComponentHocInfo) => types.Constructor; - // const whitelist: string[] = []; interface IProps { @@ -50,6 +49,63 @@ enum RerenderType { I18nChanged = 'I18nChanged', } +// 缓存 Leaf 层组件,防止重新渲染问题 +const leafComponentCache: { + [componentName: string]: any; +} = {}; +// 缓存导致 rerender 的订阅事件 +const rerenderEventCache: { + [componentId: string]: any; +} = {}; + +/** 部分没有渲染的 node 节点进行兜底处理 or 渲染方式没有渲染 LeafWrapper */ +function makeRerenderEvent({ + schema, + __debug, + container, + getNode, +}: any) { + const leaf = getNode?.(schema.id); + if (!leaf + || rerenderEventCache[schema.id]?.clear + || leaf === rerenderEventCache[schema.id]?.leaf + ) { + return; + } + rerenderEventCache[schema.id]?.dispose.forEach((d: any) => d && d()); + rerenderEventCache[schema.id] = { + clear: false, + leaf, + dispose: [ + leaf?.onPropChange?.(() => { + __debug(`${schema.componentName}[${schema.id}] leaf not render in SimulatorRendererView, leaf onPropsChange make rerender`); + container.rerender(); + }), + leaf?.onChildrenChange?.(() => { + __debug(`${schema.componentName}[${schema.id}] leaf not render in SimulatorRendererView, leaf onChildrenChange make rerender`); + container.rerender(); + }) as Function, + leaf?.onVisibleChange?.(() => { + __debug(`${schema.componentName}[${schema.id}] leaf not render in SimulatorRendererView, leaf onVisibleChange make rerender`); + container.rerender(); + }), + ], + }; +} + +/** 渲染的 node 节点全局注册事件清除 */ +function clearRerenderEvent(id: string): void { + if (!rerenderEventCache[id]) { + rerenderEventCache[id] = { + clear: true, + }; + return; + } + rerenderEventCache[id].dispose.forEach((d: any) => d && d()); + rerenderEventCache[id].dispose = []; + rerenderEventCache[id].clear = true; +} + // 给每个组件包裹一个 HOC Leaf,支持组件内部属性变化,自响应渲染 export function leafWrapper(Comp: types.IBaseRenderer, { schema, @@ -72,16 +128,15 @@ export function leafWrapper(Comp: types.IBaseRenderer, { console.error(`${schema.componentName} component may be has errors: `, Comp); } - /** 部分没有渲染的 node 节点进行兜底处理 or 渲染方式没有渲染 LeafWrapper */ - let wrapDisposeFunctions: Function[] = []; - if (getNode) { - const leaf = getNode(schema.id); + makeRerenderEvent({ + schema, + __debug, + container, + getNode, + }); - wrapDisposeFunctions = [ - leaf?.onPropsChange?.(() => container.rerender()), - leaf?.onChildrenChange?.(() => container.rerender()), - leaf?.onVisibleChange?.(() => container.rerender()), - ]; + if (leafComponentCache[schema.componentName]) { + return leafComponentCache[schema.componentName]; } class LeafWrapper extends Component { @@ -94,6 +149,8 @@ export function leafWrapper(Comp: types.IBaseRenderer, { disposeFunctions: ((() => void) | Function)[] = []; + __component_tag = 'leafWrapper'; + recordTime = () => { if (!this.recordInfo.startTime) { return; @@ -117,10 +174,11 @@ export function leafWrapper(Comp: types.IBaseRenderer, { constructor(props: IProps, context: any) { super(props, context); // 监听以下事件,当变化时更新自己 + clearRerenderEvent(schema.id); this.initOnPropsChangeEvent(); this.initOnChildrenChangeEvent(); this.initOnVisibleChangeEvent(); - wrapDisposeFunctions.forEach(d => d && d()); + __debug(`${schema.componentName}[${schema.id}] leaf render in SimulatorRendererView`); this.state = { nodeChildren: null, childrenInState: false, @@ -324,5 +382,7 @@ export function leafWrapper(Comp: types.IBaseRenderer, { LeafWrapper.displayName = (Comp as any).displayName; + leafComponentCache[schema.componentName] = LeafWrapper; + return LeafWrapper; } \ No newline at end of file diff --git a/packages/renderer-core/src/renderer/base.tsx b/packages/renderer-core/src/renderer/base.tsx index 5018342bb..87f4ad919 100644 --- a/packages/renderer-core/src/renderer/base.tsx +++ b/packages/renderer-core/src/renderer/base.tsx @@ -62,8 +62,6 @@ export default function baseRenererFactory() { static contextType = AppContext; - __hoc_components: any = {}; - __namespace = 'base'; _self: any = null; @@ -481,28 +479,20 @@ export default function baseRenererFactory() { props: transformArrayToMap(componentInfo.props, 'name'), }) || {}; - if (!this.__hoc_components[schema.componentName]) { - this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => { - Comp = ComponentConstruct(Comp, { - schema, - componentInfo, - baseRenderer: this, - }); + this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => { + Comp = ComponentConstruct(Comp, { + schema, + componentInfo, + baseRenderer: this, }); - } + }); // 对于可以获取到ref的组件做特殊处理 - if (!acceptsRef(Comp) && !this.__hoc_components[schema.componentName]) { + if (!acceptsRef(Comp)) { Comp = compWrapper(Comp); components[schema.componentName] = Comp; } - if (!this.__hoc_components[schema.componentName]) { - this.__hoc_components[schema.componentName] = Comp; - } else { - Comp = this.__hoc_components[schema.componentName]; - } - otherProps.ref = (ref: any) => { this.$(props.fieldId || props.ref, ref); // 收集ref const refProps = props.ref; @@ -824,18 +814,13 @@ export default function baseRenererFactory() { }; __getHocComp(Comp: any, schema: any) { - if (!this.__hoc_components[schema.componentName]) { - this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => { - Comp = ComponentConstruct(Comp || Div, { - schema, - componentInfo: {}, - baseRenderer: this, - }); + this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => { + Comp = ComponentConstruct(Comp || Div, { + schema, + componentInfo: {}, + baseRenderer: this, }); - this.__hoc_components[schema.componentName] = Comp; - } else { - Comp = this.__hoc_components[schema.componentName]; - } + }); return Comp; }