fix: 修复部分节点无法监听事件问题/修复渲染问题

This commit is contained in:
liujuping.liujupin 2021-09-26 14:39:42 +08:00 committed by lihao.ylh
parent 59af249ac2
commit 4c552124ae
5 changed files with 90 additions and 43 deletions

View File

@ -209,6 +209,7 @@ class Renderer extends Component<{
onCompGetRef={(schema: any, ref: any) => {
documentInstance.mountInstance(schema.id, ref);
}}
getNode={(id: string) => documentInstance.getNode(id) as any}
customCreateElement={(Component: any, props: any, children: any) => {
const { __id, ...viewProps } = props;
viewProps.componentId = __id;

View File

@ -4,7 +4,7 @@ import cn from 'classnames';
import { Node } from '@ali/lowcode-designer';
import LowCodeRenderer from '@ali/lowcode-react-renderer';
import { observer } from 'mobx-react';
import { getClosestNode } from '@ali/lowcode-utils';
import { getClosestNode, isFromVC } from '@ali/lowcode-utils';
import { GlobalEvent } from '@ali/lowcode-types';
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
import { host } from './host';
@ -132,6 +132,10 @@ class Renderer extends Component<{
startTime: number | null = null;
componentDidUpdate() {
this.recordTime();
}
recordTime() {
if (this.startTime) {
const time = Date.now() - this.startTime;
const nodeCount = host.designer.currentDocument?.getNodeCount?.();
@ -144,6 +148,10 @@ class Renderer extends Component<{
}
}
componentDidMount() {
this.recordTime();
}
render() {
const { documentInstance, rendererContainer: renderer } = this.props;
const { container } = documentInstance;
@ -166,11 +174,14 @@ class Renderer extends Component<{
device={device}
suspended={renderer.suspended}
self={renderer.scope}
getNode={(id: string) => documentInstance.getNode(id) as Node}
customCreateElement={(Component: any, props: any, children: any) => {
const { __id, ...viewProps } = props;
viewProps.componentId = __id;
const leaf = documentInstance.getNode(__id) as Node;
if (isFromVC(leaf?.componentMeta)) {
viewProps._leaf = leaf;
}
viewProps._componentName = leaf?.componentName;
// 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动
if (

View File

@ -4,7 +4,12 @@ import { EngineOptions } from '@ali/lowcode-editor-core';
import adapter from '../adapter';
import * as types from '../types/index';
const compDefaultPropertyNames = ['$$typeof', 'render', 'defaultProps'];
const compDefaultPropertyNames = [
'$$typeof',
'render',
'defaultProps',
'props',
];
export interface IComponentHocInfo {
schema: any;
@ -31,6 +36,8 @@ interface IProps {
componentId?: number;
children?: Node[];
__tag?: number;
}
enum RerenderType {
@ -55,10 +62,20 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
} = baseRenderer;
const engine = baseRenderer.context.engine;
const host: BuiltinSimulatorHost = baseRenderer.props.__host;
const getNode = baseRenderer.props?.getNode;
const container: BuiltinSimulatorHost = baseRenderer.props.__container;
const editor = host?.designer?.editor;
const { Component } = adapter.getRuntime();
/** 部分没有渲染的 node 节点进行兜底处理 or 渲染方式没有渲染 LeafWrapper */
const leaf = getNode(schema.id);
const wrapDisposeFunctions: Function[] = [
leaf?.onPropsChange?.(() => container.rerender()),
leaf?.onChildrenChange?.(() => container.rerender()),
leaf?.onVisibleChange?.(() => container.rerender()),
];
class LeafWrapper extends Component {
recordInfo: {
startTime?: number | null;
@ -96,9 +113,11 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
this.initOnPropsChangeEvent();
this.initOnChildrenChangeEvent();
this.initOnVisibleChangeEvent();
wrapDisposeFunctions.forEach(d => d && d());
this.state = {
nodeChildren: null,
childrenInState: false,
__tag: props.__tag,
};
}
@ -109,8 +128,25 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
this.recordInfo.node = node;
}
get isInWhitelist() {
return whitelist.includes(schema.componentName);
}
static getDerivedStateFromProps(props: any, state: any) {
if (props.__tag === state.__tag) {
return null;
}
return {
nodeChildren: props.children,
nodeProps: props.nodeProps,
childrenInState: true,
__tag: props.__tag,
};
}
shouldComponentUpdate() {
if (whitelist.includes(schema.componentName)) {
if (this.isInWhitelist) {
__debug(`${schema.componentName} is in leaf Hoc whitelist`);
container.rerender();
return false;
@ -130,6 +166,7 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
// 如果循坏条件变化,从根节点重新渲染
// 目前多层循坏无法判断需要从哪一层开始渲染,故先粗暴解决
if (key === '___loop___') {
__debug('key is ___loop___, render a page!');
container.rerender();
return;
}
@ -218,25 +255,7 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
}
get leaf(): Node | undefined {
return this.props._leaf;
}
get childrenMap(): any {
const map = new Map();
if (!this.hasChildren) {
return map;
}
this.children.forEach((d: any) => {
if (Array.isArray(d)) {
map.set(d[0].props.componentId, d[0]);
return;
}
map.set(d.props.componentId, d);
});
return map;
return this.props._leaf || getNode(this.props.componentId);
}
get visible(): boolean {
@ -268,6 +287,8 @@ export function leafWrapper(Comp: types.IBaseRenderer, {
if (typeof Comp === 'object') {
const compExtraPropertyNames = Object.getOwnPropertyNames(Comp).filter(d => !compDefaultPropertyNames.includes(d));
__debug(`${schema.componentName} extra property names: ${compExtraPropertyNames.join(',')}`);
compExtraPropertyNames.forEach((d: string) => {
(LeafWrapper as any)[d] = Comp[d];
});

View File

@ -342,16 +342,10 @@ export default function baseRenererFactory() {
}
const _children = this.getSchemaChildren(__schema);
let Comp = __components[__schema.componentName];
this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => {
Comp = ComponentConstruct(Comp || Div, {
schema: __schema,
componentInfo: {},
baseRenderer: this,
});
});
return this.__createVirtualDom(_children, self, ({
schema: __schema,
Comp,
Comp: this.__getHocComp(Comp, __schema),
} as IInfo));
};
@ -478,6 +472,9 @@ export default function baseRenererFactory() {
if (engine?.props?.designMode) {
otherProps.__designMode = engine.props.designMode;
}
if (this._designModeIsDesign) {
otherProps.__tag = Math.random();
}
const componentInfo: any = {};
const props: any = this.__getComponentProps(schema, Comp, {
...componentInfo,
@ -494,7 +491,6 @@ export default function baseRenererFactory() {
});
}
// 对于可以获取到ref的组件做特殊处理
if (!acceptsRef(Comp) && !this.__hoc_components[schema.componentName]) {
Comp = compWrapper(Comp);
@ -605,8 +601,8 @@ export default function baseRenererFactory() {
_children.forEach((_child: any) => {
const _childVirtualDom = this.__createVirtualDom(
isJSExpression(_child) ? parseExpression(_child, self) : _child,
self,
isJSExpression(_child) ? parseExpression(_child, this.self) : _child,
this.self,
{
schema,
Comp,
@ -813,7 +809,6 @@ export default function baseRenererFactory() {
__renderContextProvider = (customProps?: object, children?: any) => {
customProps = customProps || {};
children = children || this.__createDom();
this.__hoc_components = {};
return createElement(AppContext.Provider, {
value: {
...this.context,
@ -828,26 +823,37 @@ export default function baseRenererFactory() {
return createElement(AppContext.Consumer, {}, children);
};
__getHocComp(Comp: any, schema: any) {
if (!this.__hoc_components[schema.componentName]) {
this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => {
Comp = ComponentConstruct(Comp || Div, {
schema,
componentInfo: {},
baseRenderer: this,
});
});
} else {
Comp = this.__hoc_components[schema.componentName];
this.__hoc_components[schema.componentName] = Comp;
}
return Comp;
}
__renderComp(Comp: any, ctxProps: object) {
const { __schema } = this.props;
Comp = this.__getHocComp(Comp, __schema);
const data = this.__parseProps(__schema?.props, this.self, '', {
schema: __schema,
Comp,
componentInfo: {},
});
this.__hoc_components = {};
const { className } = data;
const { engine } = this.context || {};
if (!engine) {
return null;
}
this.componentHoc.forEach((ComponentConstruct: IComponentConstruct) => {
Comp = ComponentConstruct(Comp || Div, {
schema: __schema,
componentInfo: {},
baseRenderer: this,
});
});
const child = engine.createElement(
Comp,
{

View File

@ -61,6 +61,14 @@ export function arrShallowEquals(arr1: any[], arr2: any[]): boolean {
return arr1.every(item => arr2.includes(item));
}
/**
* meta vc prototype
* @param meta
*/
export function isFromVC(meta: ComponentMeta) {
return !!meta?.getMetadata()?.experimental;
}
export function executePendingFn(fn: () => void, timeout: number = 2000) {
return setTimeout(fn, timeout);
}