Merge branch 'develop' into release/1.1.11-beta

This commit is contained in:
JackLian 2023-10-16 14:35:53 +08:00
commit 57267ed823
8 changed files with 77 additions and 68 deletions

View File

@ -58,7 +58,7 @@ sidebar_position: 1
## 协议的作用 ## 协议的作用
基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升各平台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。 基于统一的协议,我们完成业务组件、区块、模板等各类物料的标准统一,各类中后台研发系统生产的物料可借助物料中心进行跨系统流通,通过丰富物料生态的共享提升各平台研发系统的效率。同时完成低代码引擎的标准统一以及低代码搭建中台能力的输出,帮助业务方快速孵化本业务域中后台研发系统。
### 打破物料孤岛 ### 打破物料孤岛

View File

@ -1,6 +1,6 @@
{ {
"name": "@alilc/lowcode-engine-docs", "name": "@alilc/lowcode-engine-docs",
"version": "1.1.10", "version": "1.1.11",
"description": "低代码引擎版本化文档", "description": "低代码引擎版本化文档",
"license": "MIT", "license": "MIT",
"files": [ "files": [

View File

@ -31,6 +31,7 @@ exports[`Base should be render Text 1`] = `
behavior="NORMAL" behavior="NORMAL"
componentId="node_ockvuu8u916" componentId="node_ockvuu8u916"
fieldId="text_kvuu9gl2" fieldId="text_kvuu9gl2"
forwardRef={[Function]}
maxLine={0} maxLine={0}
showTitle={false} showTitle={false}
> >

View File

@ -1,20 +1,72 @@
import { cloneEnumerableProperty } from '@alilc/lowcode-utils'; import { cloneEnumerableProperty } from '@alilc/lowcode-utils';
import adapter from '../adapter'; import adapter from '../adapter';
import { IBaseRendererInstance, IRendererProps } from '../types';
export function compWrapper(Comp: any) { function patchDidCatch(Comp: any, { baseRenderer }: { baseRenderer: IBaseRendererInstance }) {
if (Comp.patchedCatch) {
return;
}
Comp.patchedCatch = true;
const { PureComponent } = adapter.getRuntime();
// Rax 的 getDerivedStateFromError 有 BUG这里先用 componentDidCatch 来替代
// @see https://github.com/alibaba/rax/issues/2211
const originalDidCatch = Comp.prototype.componentDidCatch;
Comp.prototype.componentDidCatch = function didCatch(this: any, error: Error, errorInfo: any) {
this.setState({ engineRenderError: true, error });
if (originalDidCatch && typeof originalDidCatch === 'function') {
originalDidCatch.call(this, error, errorInfo);
}
};
const { engine } = baseRenderer.context;
const originRender = Comp.prototype.render;
Comp.prototype.render = function () {
if (this.state && this.state.engineRenderError) {
this.state.engineRenderError = false;
return engine.createElement(engine.getFaultComponent(), {
...this.props,
error: this.state.error,
componentName: this.props._componentName,
});
}
return originRender.call(this);
};
if (!(Comp.prototype instanceof PureComponent)) {
const originShouldComponentUpdate = Comp.prototype.shouldComponentUpdate;
Comp.prototype.shouldComponentUpdate = function (nextProps: IRendererProps, nextState: any) {
if (nextState && nextState.engineRenderError) {
return true;
}
return originShouldComponentUpdate
? originShouldComponentUpdate.call(this, nextProps, nextState)
: true;
};
}
}
export function compWrapper(Comp: any, options: { baseRenderer: IBaseRendererInstance }) {
const { createElement, Component, forwardRef } = adapter.getRuntime(); const { createElement, Component, forwardRef } = adapter.getRuntime();
if (
Comp?.prototype?.isReactComponent || // react
Comp?.prototype?.setState || // rax
Comp?.prototype instanceof Component
) {
patchDidCatch(Comp, options);
return Comp;
}
class Wrapper extends Component { class Wrapper extends Component {
// constructor(props: any, context: any) {
// super(props, context);
// }
render() { render() {
return createElement(Comp, this.props); return createElement(Comp, { ...this.props, ref: this.props.forwardRef });
} }
} }
(Wrapper as any).displayName = Comp.displayName; (Wrapper as any).displayName = Comp.displayName;
return cloneEnumerableProperty(forwardRef((props: any, ref: any) => { patchDidCatch(Wrapper, options);
return createElement(Wrapper, { ...props, forwardRef: ref });
}), Comp); return cloneEnumerableProperty(
forwardRef((props: any, ref: any) => {
return createElement(Wrapper, { ...props, forwardRef: ref });
}),
Comp,
);
} }

View File

@ -23,7 +23,6 @@ import {
transformStringToFunction, transformStringToFunction,
checkPropTypes, checkPropTypes,
getI18n, getI18n,
canAcceptsRef,
getFileCssName, getFileCssName,
capitalizeFirstLetter, capitalizeFirstLetter,
DataHelper, DataHelper,
@ -616,11 +615,8 @@ export default function baseRendererFactory(): IBaseRenderComponent {
}); });
}); });
// 对于不可以接收到 ref 的组件需要做特殊处理 Comp = compWrapper(Comp, { baseRenderer: this });
if (!canAcceptsRef(Comp)) { components[schema.componentName] = Comp;
Comp = compWrapper(Comp);
components[schema.componentName] = Comp;
}
otherProps.ref = (ref: any) => { otherProps.ref = (ref: any) => {
this.$(props.fieldId || props.ref, ref); // 收集ref this.$(props.fieldId || props.ref, ref); // 收集ref

View File

@ -105,55 +105,7 @@ export default function rendererFactory(): IRenderComponent {
return SetComponent; return SetComponent;
} }
patchDidCatch(SetComponent: any) {
if (!this.isValidComponent(SetComponent)) {
return;
}
if (SetComponent.patchedCatch) {
return;
}
if (!SetComponent.prototype) {
return;
}
SetComponent.patchedCatch = true;
// Rax 的 getDerivedStateFromError 有 BUG这里先用 componentDidCatch 来替代
// @see https://github.com/alibaba/rax/issues/2211
const originalDidCatch = SetComponent.prototype.componentDidCatch;
SetComponent.prototype.componentDidCatch = function didCatch(this: any, error: Error, errorInfo: any) {
this.setState({ engineRenderError: true, error });
if (originalDidCatch && typeof originalDidCatch === 'function') {
originalDidCatch.call(this, error, errorInfo);
}
};
const engine = this;
const originRender = SetComponent.prototype.render;
SetComponent.prototype.render = function () {
if (this.state && this.state.engineRenderError) {
this.state.engineRenderError = false;
return engine.createElement(engine.getFaultComponent(), {
...this.props,
error: this.state.error,
componentName: this.props._componentName
});
}
return originRender.call(this);
};
if(!(SetComponent.prototype instanceof PureComponent)) {
const originShouldComponentUpdate = SetComponent.prototype.shouldComponentUpdate;
SetComponent.prototype.shouldComponentUpdate = function (nextProps: IRendererProps, nextState: any) {
if (nextState && nextState.engineRenderError) {
return true;
}
return originShouldComponentUpdate ? originShouldComponentUpdate.call(this, nextProps, nextState) : true;
};
}
}
createElement(SetComponent: any, props: any, children?: any) { createElement(SetComponent: any, props: any, children?: any) {
// TODO: enable in runtime mode?
this.patchDidCatch(SetComponent);
return (this.props.customCreateElement || createElement)(SetComponent, props, children); return (this.props.customCreateElement || createElement)(SetComponent, props, children);
} }

View File

@ -335,7 +335,6 @@ export interface IRenderComponent {
componentDidCatch(e: any): Promise<void> | void; componentDidCatch(e: any): Promise<void> | void;
shouldComponentUpdate(nextProps: IRendererProps): boolean; shouldComponentUpdate(nextProps: IRendererProps): boolean;
isValidComponent(SetComponent: any): any; isValidComponent(SetComponent: any): any;
patchDidCatch(SetComponent: any): void;
createElement(SetComponent: any, props: any, children?: any): any; createElement(SetComponent: any, props: any, children?: any): any;
getNotFoundComponent(): any; getNotFoundComponent(): any;
getFaultComponent(): any; getFaultComponent(): any;

View File

@ -10,10 +10,10 @@ export function isReactClass(obj: any): obj is ComponentClass<any> {
} }
export function acceptsRef(obj: any): boolean { export function acceptsRef(obj: any): boolean {
return obj?.prototype?.isReactComponent || (obj.$$typeof && obj.$$typeof === REACT_FORWARD_REF_TYPE); return obj?.prototype?.isReactComponent || isForwardOrMemoForward(obj);
} }
function isForwardRefType(obj: any): boolean { export function isForwardRefType(obj: any): boolean {
return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE; return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE;
} }
@ -21,6 +21,15 @@ function isMemoType(obj: any): boolean {
return obj?.$$typeof && obj.$$typeof === REACT_MEMO_TYPE; return obj?.$$typeof && obj.$$typeof === REACT_MEMO_TYPE;
} }
export function isForwardOrMemoForward(obj: any): boolean {
return obj?.$$typeof && (
// React.forwardRef(..)
isForwardRefType(obj) ||
// React.memo(React.forwardRef(..))
(isMemoType(obj) && isForwardRefType(obj.type))
);
}
export function isReactComponent(obj: any): obj is ComponentType<any> { export function isReactComponent(obj: any): obj is ComponentType<any> {
if (!obj) { if (!obj) {
return false; return false;