mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
feat: the renderer-core leaf component removes the react.createElement call
This commit is contained in:
parent
0184dcd938
commit
c3ce042c83
@ -3,6 +3,9 @@ import { IPublicTypeNodeSchema, IPublicTypeComponentInstance, IPublicTypeNodeIns
|
||||
|
||||
export interface BuiltinSimulatorRenderer {
|
||||
readonly isSimulatorRenderer: true;
|
||||
autoRepaintNode?: boolean;
|
||||
components: Record<string, Component>;
|
||||
rerender: () => void;
|
||||
createComponent(schema: IPublicTypeNodeSchema): Component | null;
|
||||
getComponent(componentName: string): Component;
|
||||
getClosestNodeInstance(
|
||||
|
||||
@ -64,6 +64,7 @@ export interface IDocumentModel extends Omit< IPublicModelDocumentModel, 'select
|
||||
dragObject: IPublicTypeDragNodeObject | IPublicTypeNodeSchema | INode | IPublicTypeDragNodeDataObject,
|
||||
): boolean;
|
||||
|
||||
getNodeCount(): number;
|
||||
}
|
||||
|
||||
export class DocumentModel implements IDocumentModel {
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
IPublicModelNode,
|
||||
IPublicModelExclusiveGroup,
|
||||
IPublicEnumTransformStage,
|
||||
IPublicTypeDisposable,
|
||||
} from '@alilc/lowcode-types';
|
||||
import { compatStage, isDOMText, isJSExpression, isNode } from '@alilc/lowcode-utils';
|
||||
import { SettingTopEntry } from '@alilc/lowcode-designer';
|
||||
@ -112,6 +113,10 @@ export interface INode extends IPublicModelNode {
|
||||
replaceChild(node: INode, data: any): INode;
|
||||
|
||||
getSuitablePlace(node: INode, ref: any): any;
|
||||
|
||||
onChildrenChange(fn: (param?: { type: string; node: INode }) => void): IPublicTypeDisposable;
|
||||
|
||||
onPropChange(func: (info: IPublicTypePropChangeOptions) => void): IPublicTypeDisposable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1080,7 +1085,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
return this.props;
|
||||
}
|
||||
|
||||
onChildrenChange(fn: (param?: { type: string; node: Node }) => void): (() => void) | undefined {
|
||||
onChildrenChange(fn: (param?: { type: string; node: Node }) => void): IPublicTypeDisposable {
|
||||
const wrappedFunc = wrapWithEventSwitch(fn);
|
||||
return this.children?.onChange(wrappedFunc);
|
||||
}
|
||||
@ -1273,7 +1278,7 @@ export class Node<Schema extends IPublicTypeNodeSchema = IPublicTypeNodeSchema>
|
||||
this.emitter?.emit('propChange', val);
|
||||
}
|
||||
|
||||
onPropChange(func: (info: IPublicTypePropChangeOptions) => void): Function {
|
||||
onPropChange(func: (info: IPublicTypePropChangeOptions) => void): IPublicTypeDisposable {
|
||||
const wrappedFunc = wrapWithEventSwitch(func);
|
||||
this.emitter.on('propChange', wrappedFunc);
|
||||
return () => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { BuiltinSimulatorHost, Node, IPublicTypePropChangeOptions } from '@alilc/lowcode-designer';
|
||||
import { INode, IPublicTypePropChangeOptions } from '@alilc/lowcode-designer';
|
||||
import { GlobalEvent, IPublicEnumTransformStage, IPublicTypeNodeSchema, IPublicTypeEngineOptions } from '@alilc/lowcode-types';
|
||||
import { isReactComponent, cloneEnumerableProperty } from '@alilc/lowcode-utils';
|
||||
import { debounce } from '../utils/common';
|
||||
@ -16,15 +16,17 @@ export interface IComponentHocProps {
|
||||
__tag: any;
|
||||
componentId: any;
|
||||
_leaf: any;
|
||||
forwardedRef: any;
|
||||
forwardedRef?: any;
|
||||
}
|
||||
|
||||
export interface IComponentHocState {
|
||||
childrenInState: boolean;
|
||||
nodeChildren: any;
|
||||
nodeCacheProps: any;
|
||||
|
||||
/** 控制是否显示隐藏 */
|
||||
visible: boolean;
|
||||
|
||||
/** 控制是否渲染 */
|
||||
condition: boolean;
|
||||
nodeProps: any;
|
||||
@ -40,15 +42,17 @@ export interface IComponentHoc {
|
||||
export type IComponentConstruct = (Comp: types.IBaseRenderComponent, info: IComponentHocInfo) => types.IGeneralConstructor;
|
||||
|
||||
interface IProps {
|
||||
_leaf: Node | undefined;
|
||||
_leaf: INode | undefined;
|
||||
|
||||
visible: boolean;
|
||||
|
||||
componentId?: number;
|
||||
componentId: number;
|
||||
|
||||
children?: Node[];
|
||||
children?: INode[];
|
||||
|
||||
__tag?: number;
|
||||
__tag: number;
|
||||
|
||||
forwardedRef?: any;
|
||||
}
|
||||
|
||||
enum RerenderType {
|
||||
@ -61,8 +65,7 @@ enum RerenderType {
|
||||
|
||||
// 缓存 Leaf 层组件,防止重新渲染问题
|
||||
class LeafCache {
|
||||
constructor(public documentId: string, public device: string) {
|
||||
}
|
||||
|
||||
/** 组件缓存 */
|
||||
component = new Map();
|
||||
|
||||
@ -77,6 +80,9 @@ class LeafCache {
|
||||
event = new Map();
|
||||
|
||||
ref = new Map();
|
||||
|
||||
constructor(public documentId: string, public device: string) {
|
||||
}
|
||||
}
|
||||
|
||||
let cache: LeafCache;
|
||||
@ -155,11 +161,11 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
const curDocumentId = baseRenderer.props?.documentId ?? '';
|
||||
const curDevice = baseRenderer.props?.device ?? '';
|
||||
const getNode = baseRenderer.props?.getNode;
|
||||
const container: BuiltinSimulatorHost = baseRenderer.props?.__container;
|
||||
const container = baseRenderer.props?.__container;
|
||||
const setSchemaChangedSymbol = baseRenderer.props?.setSchemaChangedSymbol;
|
||||
const editor = host?.designer?.editor;
|
||||
const runtime = adapter.getRuntime();
|
||||
const { forwardRef } = runtime;
|
||||
const { forwardRef, createElement } = runtime;
|
||||
const Component = runtime.Component as types.IGeneralConstructor<
|
||||
IComponentHocProps, IComponentHocState
|
||||
>;
|
||||
@ -192,14 +198,64 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
recordInfo: {
|
||||
startTime?: number | null;
|
||||
type?: string;
|
||||
node?: Node;
|
||||
node?: INode;
|
||||
} = {};
|
||||
|
||||
private curEventLeaf: INode | undefined;
|
||||
|
||||
static displayName = schema.componentName;
|
||||
|
||||
disposeFunctions: Array<((() => void) | Function)> = [];
|
||||
|
||||
__component_tag = 'leafWrapper';
|
||||
|
||||
renderUnitInfo: {
|
||||
minimalUnitId?: string;
|
||||
minimalUnitName?: string;
|
||||
singleRender?: boolean;
|
||||
};
|
||||
|
||||
// 最小渲染单元做防抖处理
|
||||
makeUnitRenderDebounced = debounce(() => {
|
||||
this.beforeRender(RerenderType.MinimalRenderUnit);
|
||||
const schema = this.leaf?.export?.(IPublicEnumTransformStage.Render);
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
const nextProps = getProps(schema, scope, Comp, componentInfo);
|
||||
const children = getChildren(schema, scope, Comp);
|
||||
const nextState = {
|
||||
nodeProps: nextProps,
|
||||
nodeChildren: children,
|
||||
childrenInState: true,
|
||||
};
|
||||
if ('children' in nextProps) {
|
||||
nextState.nodeChildren = nextProps.children;
|
||||
}
|
||||
|
||||
__debug(`${this.leaf?.componentName}(${this.props.componentId}) MinimalRenderUnit Render!`);
|
||||
this.setState(nextState);
|
||||
}, 20);
|
||||
|
||||
constructor(props: IProps, context: any) {
|
||||
super(props, context);
|
||||
// 监听以下事件,当变化时更新自己
|
||||
__debug(`${schema.componentName}[${this.props.componentId}] leaf render in SimulatorRendererView`);
|
||||
clearRerenderEvent(componentCacheId);
|
||||
this.curEventLeaf = this.leaf;
|
||||
|
||||
cache.ref.set(componentCacheId, {
|
||||
makeUnitRender: this.makeUnitRender,
|
||||
});
|
||||
|
||||
let cacheState = cache.state.get(componentCacheId);
|
||||
if (!cacheState || cacheState.__tag !== props.__tag) {
|
||||
cacheState = this.getDefaultState(props);
|
||||
}
|
||||
|
||||
this.state = cacheState;
|
||||
}
|
||||
|
||||
recordTime = () => {
|
||||
if (!this.recordInfo.startTime) {
|
||||
return;
|
||||
@ -216,6 +272,14 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
this.recordInfo.startTime = null;
|
||||
};
|
||||
|
||||
makeUnitRender = () => {
|
||||
this.makeUnitRenderDebounced();
|
||||
};
|
||||
|
||||
get autoRepaintNode() {
|
||||
return container?.autoRepaintNode;
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.recordTime();
|
||||
}
|
||||
@ -243,27 +307,6 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props: IProps, context: any) {
|
||||
super(props, context);
|
||||
// 监听以下事件,当变化时更新自己
|
||||
__debug(`${schema.componentName}[${this.props.componentId}] leaf render in SimulatorRendererView`);
|
||||
clearRerenderEvent(componentCacheId);
|
||||
this.curEventLeaf = this.leaf;
|
||||
|
||||
cache.ref.set(componentCacheId, {
|
||||
makeUnitRender: this.makeUnitRender,
|
||||
});
|
||||
|
||||
let cacheState = cache.state.get(componentCacheId);
|
||||
if (!cacheState || cacheState.__tag !== props.__tag) {
|
||||
cacheState = this.getDefaultState(props);
|
||||
}
|
||||
|
||||
this.state = cacheState;
|
||||
}
|
||||
|
||||
private curEventLeaf: Node | undefined;
|
||||
|
||||
setState(state: any) {
|
||||
cache.state.set(componentCacheId, {
|
||||
...this.state,
|
||||
@ -274,23 +317,13 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
|
||||
/** 由于内部属性变化,在触发渲染前,会执行该函数 */
|
||||
beforeRender(type: string, node?: Node): void {
|
||||
beforeRender(type: string, node?: INode): void {
|
||||
this.recordInfo.startTime = Date.now();
|
||||
this.recordInfo.type = type;
|
||||
this.recordInfo.node = node;
|
||||
setSchemaChangedSymbol?.(true);
|
||||
}
|
||||
|
||||
renderUnitInfo: {
|
||||
minimalUnitId?: string;
|
||||
minimalUnitName?: string;
|
||||
singleRender?: boolean;
|
||||
};
|
||||
|
||||
get autoRepaintNode() {
|
||||
return container.autoRepaintNode;
|
||||
}
|
||||
|
||||
judgeMiniUnitRender() {
|
||||
if (!this.renderUnitInfo) {
|
||||
this.getRenderUnitInfo();
|
||||
@ -308,7 +341,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
|
||||
if (!ref) {
|
||||
__debug('Cant find minimalRenderUnit ref! This make rerender!');
|
||||
container.rerender();
|
||||
container?.rerender();
|
||||
return;
|
||||
}
|
||||
__debug(`${this.leaf?.componentName}(${this.props.componentId}) need render, make its minimalRenderUnit ${renderUnitInfo.minimalUnitName}(${renderUnitInfo.minimalUnitId})`);
|
||||
@ -321,7 +354,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
return;
|
||||
}
|
||||
|
||||
if (leaf.isRoot()) {
|
||||
if (leaf.isRootNode) {
|
||||
this.renderUnitInfo = {
|
||||
singleRender: true,
|
||||
...(this.renderUnitInfo || {}),
|
||||
@ -347,32 +380,6 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
}
|
||||
|
||||
// 最小渲染单元做防抖处理
|
||||
makeUnitRenderDebounced = debounce(() => {
|
||||
this.beforeRender(RerenderType.MinimalRenderUnit);
|
||||
const schema = this.leaf?.export?.(IPublicEnumTransformStage.Render);
|
||||
if (!schema) {
|
||||
return;
|
||||
}
|
||||
const nextProps = getProps(schema, scope, Comp, componentInfo);
|
||||
const children = getChildren(schema, scope, Comp);
|
||||
const nextState = {
|
||||
nodeProps: nextProps,
|
||||
nodeChildren: children,
|
||||
childrenInState: true,
|
||||
};
|
||||
if ('children' in nextProps) {
|
||||
nextState.nodeChildren = nextProps.children;
|
||||
}
|
||||
|
||||
__debug(`${this.leaf?.componentName}(${this.props.componentId}) MinimalRenderUnit Render!`);
|
||||
this.setState(nextState);
|
||||
}, 20);
|
||||
|
||||
makeUnitRender = () => {
|
||||
this.makeUnitRenderDebounced();
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps: any) {
|
||||
let { componentId } = nextProps;
|
||||
if (nextProps.__tag === this.props.__tag) {
|
||||
@ -420,7 +427,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
// 目前多层循坏无法判断需要从哪一层开始渲染,故先粗暴解决
|
||||
if (key === '___loop___') {
|
||||
__debug('key is ___loop___, render a page!');
|
||||
container.rerender();
|
||||
container?.rerender();
|
||||
// 由于 scope 变化,需要清空缓存,使用新的 scope
|
||||
cache.component.delete(componentCacheId);
|
||||
return;
|
||||
@ -536,7 +543,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
return [];
|
||||
}
|
||||
|
||||
get leaf(): Node | undefined {
|
||||
get leaf(): INode | undefined {
|
||||
if (this.props._leaf?.isMock) {
|
||||
// 低代码组件作为一个整体更新,其内部的组件不需要监听相关事件
|
||||
return undefined;
|
||||
@ -570,13 +577,12 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
}
|
||||
|
||||
let LeafWrapper = forwardRef((props: any, ref: any) => (
|
||||
// @ts-ignore
|
||||
<LeafHoc
|
||||
{...props}
|
||||
forwardedRef={ref}
|
||||
/>
|
||||
));
|
||||
let LeafWrapper = forwardRef((props: any, ref: any) => {
|
||||
return createElement(LeafHoc, {
|
||||
...props,
|
||||
forwardedRef: ref,
|
||||
});
|
||||
});
|
||||
|
||||
LeafWrapper = cloneEnumerableProperty(LeafWrapper, Comp);
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import classnames from 'classnames';
|
||||
import { create as createDataSourceEngine } from '@alilc/lowcode-datasource-engine/interpret';
|
||||
import { IPublicTypeNodeSchema, IPublicTypeNodeData, JSONValue, IPublicTypeCompositeValue } from '@alilc/lowcode-types';
|
||||
import { IPublicTypeNodeSchema, IPublicTypeNodeData, IPublicTypeJSONValue, IPublicTypeCompositeValue } from '@alilc/lowcode-types';
|
||||
import { isI18nData, isJSExpression, isJSFunction } from '@alilc/lowcode-utils';
|
||||
import adapter from '../adapter';
|
||||
import divFactory from '../components/Div';
|
||||
@ -121,6 +121,8 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
let scopeIdx = 0;
|
||||
|
||||
return class BaseRenderer extends Component<IBaseRendererProps, Record<string, any>> {
|
||||
[key: string]: any;
|
||||
|
||||
static displayName = 'BaseRenderer';
|
||||
|
||||
static defaultProps = {
|
||||
@ -139,6 +141,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
__compScopes: Record<string, any> = {};
|
||||
__instanceMap: Record<string, any> = {};
|
||||
__dataHelper: any;
|
||||
|
||||
/**
|
||||
* keep track of customMethods added to this context
|
||||
*
|
||||
@ -155,8 +158,6 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
*/
|
||||
__styleElement: any;
|
||||
|
||||
[key: string]: any;
|
||||
|
||||
constructor(props: IBaseRendererProps, context: IBaseRendererContext) {
|
||||
super(props, context);
|
||||
this.context = context;
|
||||
@ -242,6 +243,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
super.forceUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* execute method in schema.lifeCycles
|
||||
* @PRIVATE
|
||||
@ -490,6 +492,10 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
}
|
||||
|
||||
const _children = getSchemaChildren(schema);
|
||||
if (!schema.componentName) {
|
||||
logger.error('The componentName in the schema is invalid, please check the schema: ', schema);
|
||||
return;
|
||||
}
|
||||
// 解析占位组件
|
||||
if (schema.componentName === 'Fragment' && _children) {
|
||||
const tarChildren = isJSExpression(_children) ? this.__parseExpression(_children, scope) : _children;
|
||||
@ -758,7 +764,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
const itemArg = (schema.loopArgs && schema.loopArgs[0]) || DEFAULT_LOOP_ARG_ITEM;
|
||||
const indexArg = (schema.loopArgs && schema.loopArgs[1]) || DEFAULT_LOOP_ARG_INDEX;
|
||||
const { loop } = schema;
|
||||
return loop.map((item: JSONValue | IPublicTypeCompositeValue, i: number) => {
|
||||
return loop.map((item: IPublicTypeJSONValue | IPublicTypeCompositeValue, i: number) => {
|
||||
const loopSelf: any = {
|
||||
[itemArg]: item,
|
||||
[indexArg]: i,
|
||||
|
||||
@ -6,6 +6,7 @@ import baseRendererFactory from './base';
|
||||
import divFactory from '../components/Div';
|
||||
import { IRenderComponent, IRendererProps, IRendererState } from '../types';
|
||||
import { IPublicTypeNodeSchema, IPublicTypeRootSchema } from '@alilc/lowcode-types';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
export default function rendererFactory(): IRenderComponent {
|
||||
const { PureComponent, Component, createElement, findDOMNode } = adapter.getRuntime();
|
||||
@ -168,6 +169,7 @@ export default function rendererFactory(): IRenderComponent {
|
||||
}
|
||||
// 兼容乐高区块模板
|
||||
if (schema.componentName !== 'Div' && !isFileSchema(schema)) {
|
||||
logger.error('The root component name needs to be one of Page、Block、Component, please check the schema: ', schema);
|
||||
return '模型结构异常';
|
||||
}
|
||||
debug('entry.render');
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { ComponentLifecycle, CSSProperties } from 'react';
|
||||
import { BuiltinSimulatorHost } from '@alilc/lowcode-designer';
|
||||
import { BuiltinSimulatorHost, BuiltinSimulatorRenderer } from '@alilc/lowcode-designer';
|
||||
import { RequestHandler, IPublicTypeNodeSchema, IPublicTypeRootSchema, IPublicTypeJSONObject } from '@alilc/lowcode-types';
|
||||
|
||||
export type ISchema = IPublicTypeNodeSchema | IPublicTypeRootSchema;
|
||||
@ -8,16 +8,16 @@ export type ISchema = IPublicTypeNodeSchema | IPublicTypeRootSchema;
|
||||
** Duck typed component type supporting both react and rax
|
||||
*/
|
||||
interface IGeneralComponent<P = {}, S = {}, SS = any> extends ComponentLifecycle<P, S, SS> {
|
||||
readonly props: Readonly<P> & Readonly<{ children?: any | undefined }>;
|
||||
state: Readonly<S>;
|
||||
refs: Record<string, any>;
|
||||
context: any;
|
||||
setState<K extends keyof S>(
|
||||
state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
|
||||
callback?: () => void
|
||||
): void;
|
||||
forceUpdate(callback?: () => void): void;
|
||||
render(): any;
|
||||
readonly props: Readonly<P> & Readonly<{ children?: any | undefined }>;
|
||||
state: Readonly<S>;
|
||||
refs: Record<string, any>;
|
||||
context: any;
|
||||
}
|
||||
|
||||
export type IGeneralConstructor<
|
||||
@ -60,20 +60,28 @@ export interface ILocationLike {
|
||||
}
|
||||
|
||||
export type IRendererAppHelper = Partial<{
|
||||
|
||||
/** 全局公共函数 */
|
||||
utils: Record<string, any>;
|
||||
|
||||
/** 全局常量 */
|
||||
constants: Record<string, any>;
|
||||
|
||||
/** react-router 的 location 实例 */
|
||||
location: ILocationLike;
|
||||
|
||||
/** react-router 的 history 实例 */
|
||||
history: IHistoryLike;
|
||||
|
||||
/** @deprecated 已无业务使用 */
|
||||
match: any;
|
||||
|
||||
/** @experimental 内部使用 */
|
||||
logParams: Record<string, any>;
|
||||
|
||||
/** @experimental 内部使用 */
|
||||
addons: Record<string, any>;
|
||||
|
||||
/** @experimental 内部使用 */
|
||||
requestHandlersMap: Record<string, RequestHandler<{
|
||||
data: unknown;
|
||||
@ -86,25 +94,34 @@ export type IRendererAppHelper = Partial<{
|
||||
* @see @todo @承虎
|
||||
*/
|
||||
export interface IRendererProps {
|
||||
|
||||
/** 符合低代码搭建协议的数据 */
|
||||
schema: IPublicTypeRootSchema | IPublicTypeNodeSchema;
|
||||
|
||||
/** 组件依赖的实例 */
|
||||
components: Record<string, IGeneralComponent>;
|
||||
|
||||
/** CSS 类名 */
|
||||
className?: string;
|
||||
|
||||
/** style */
|
||||
style?: CSSProperties;
|
||||
|
||||
/** id */
|
||||
id?: string | number;
|
||||
|
||||
/** 语言 */
|
||||
locale?: string;
|
||||
|
||||
/**
|
||||
* 多语言语料
|
||||
* 配置规范参见《低代码搭建组件描述协议》https://lowcode-engine.cn/lowcode 中 2.6 国际化多语言支持
|
||||
* */
|
||||
messages?: Record<string, any>;
|
||||
|
||||
/** 主要用于设置渲染模块的全局上下文,里面定义的内容可以在低代码中通过 this 来访问,比如 this.utils */
|
||||
appHelper?: IRendererAppHelper;
|
||||
|
||||
/**
|
||||
* 配置规范参见《低代码搭建组件描述协议》https://lowcode-engine.cn/lowcode
|
||||
* 主要在搭建场景中使用,用于提升用户搭建体验。
|
||||
@ -112,33 +129,46 @@ export interface IRendererProps {
|
||||
* > 在生产环境下不需要设置
|
||||
*/
|
||||
componentsMap?: { [key: string]: any };
|
||||
|
||||
/** 设计模式,可选值:live、design */
|
||||
designMode?: string;
|
||||
|
||||
/** 渲染模块是否挂起,当设置为 true 时,渲染模块最外层容器的 shouldComponentUpdate 将始终返回false,在下钻编辑或者多引擎渲染的场景会用到该参数。 */
|
||||
suspended?: boolean;
|
||||
|
||||
/** 组件获取 ref 时触发的钩子 */
|
||||
onCompGetRef?: (schema: IPublicTypeNodeSchema, ref: any) => void;
|
||||
|
||||
/** 组件 ctx 更新回调 */
|
||||
onCompGetCtx?: (schema: IPublicTypeNodeSchema, ref: any) => void;
|
||||
|
||||
/** 传入的 schema 是否有变更 */
|
||||
getSchemaChangedSymbol?: () => boolean;
|
||||
|
||||
/** 设置 schema 是否有变更 */
|
||||
setSchemaChangedSymbol?: (symbol: boolean) => void;
|
||||
|
||||
/** 自定义创建 element 的钩子 */
|
||||
customCreateElement?: (Component: any, props: any, children: any) => any;
|
||||
|
||||
/** 渲染类型,标识当前模块是以什么类型进行渲染的 */
|
||||
rendererName?: 'LowCodeRenderer' | 'PageRenderer' | string;
|
||||
|
||||
/** 当找不到组件时,显示的组件 */
|
||||
notFoundComponent?: IGeneralComponent;
|
||||
|
||||
/** 当组件渲染异常时,显示的组件 */
|
||||
faultComponent?: IGeneralComponent;
|
||||
|
||||
/** 设备信息 */
|
||||
device?: string;
|
||||
|
||||
/**
|
||||
* @default true
|
||||
* JSExpression 是否只支持使用 this 来访问上下文变量
|
||||
*/
|
||||
thisRequiredInJSE?: boolean;
|
||||
|
||||
/**
|
||||
* @default false
|
||||
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
|
||||
@ -162,7 +192,7 @@ export interface IBaseRendererProps {
|
||||
__ctx: Record<string, any>;
|
||||
__schema: IPublicTypeRootSchema;
|
||||
__host?: BuiltinSimulatorHost;
|
||||
__container?: any;
|
||||
__container?: BuiltinSimulatorRenderer;
|
||||
config?: Record<string, any>;
|
||||
designMode?: 'design';
|
||||
className?: string;
|
||||
@ -173,6 +203,7 @@ export interface IBaseRendererProps {
|
||||
thisRequiredInJSE?: boolean;
|
||||
documentId?: string;
|
||||
getNode?: any;
|
||||
|
||||
/**
|
||||
* 设备类型,默认值:'default'
|
||||
*/
|
||||
@ -213,13 +244,13 @@ export interface DataSource {
|
||||
}
|
||||
|
||||
export interface IRuntime {
|
||||
[key: string]: any;
|
||||
Component: IGeneralConstructor;
|
||||
PureComponent: IGeneralConstructor;
|
||||
createElement: (...args: any) => any;
|
||||
createContext: (...args: any) => any;
|
||||
forwardRef: (...args: any) => any;
|
||||
findDOMNode: (...args: any) => any;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface IRendererModules {
|
||||
@ -285,21 +316,22 @@ export interface IBaseRenderComponent {
|
||||
}
|
||||
|
||||
export interface IRenderComponent {
|
||||
displayName: string;
|
||||
defaultProps: IRendererProps;
|
||||
findDOMNode: (...args: any) => any;
|
||||
|
||||
new(props: IRendererProps, context: any): IGeneralComponent<IRendererProps, IRendererState> & {
|
||||
[x: string]: any;
|
||||
__getRef: (ref: any) => void;
|
||||
componentDidMount(): Promise<void>;
|
||||
componentDidUpdate(): Promise<void>;
|
||||
componentWillUnmount(): Promise<void>;
|
||||
componentDidCatch(e: any): Promise<void>;
|
||||
shouldComponentUpdate(nextProps: IRendererProps): boolean;
|
||||
__getRef: (ref: any) => void;
|
||||
isValidComponent(SetComponent: any): any;
|
||||
patchDidCatch(SetComponent: any): void;
|
||||
createElement(SetComponent: any, props: any, children?: any): any;
|
||||
getNotFoundComponent(): any;
|
||||
getFaultComponent(): any;
|
||||
};
|
||||
displayName: string;
|
||||
defaultProps: IRendererProps;
|
||||
findDOMNode: (...args: any) => any;
|
||||
}
|
||||
|
||||
@ -324,6 +324,7 @@ describe('mini unit render', () => {
|
||||
it('change component leaf isRoot is true', () => {
|
||||
const TextNode = new Node(textSchema, {
|
||||
isRoot: true,
|
||||
isRootNode: true,
|
||||
});
|
||||
|
||||
nodeMap.set(textSchema.id, TextNode);
|
||||
@ -356,6 +357,7 @@ describe('mini unit render', () => {
|
||||
id: 'rootId',
|
||||
}, {
|
||||
isRoot: true,
|
||||
isRootNode: true
|
||||
}),
|
||||
})
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
import React, { Component, createElement, PureComponent, createContext } from 'react';
|
||||
import React, { Component, createElement, forwardRef, PureComponent, createContext } from 'react';
|
||||
const mockGetRenderers = jest.fn();
|
||||
const mockGetRuntime = jest.fn();
|
||||
const mockParseExpression = jest.fn();
|
||||
@ -59,6 +59,7 @@ describe('Base Render methods', () => {
|
||||
createElement,
|
||||
PureComponent,
|
||||
createContext,
|
||||
forwardRef,
|
||||
});
|
||||
RendererClass = baseRendererFactory();
|
||||
})
|
||||
|
||||
@ -40,6 +40,10 @@ export default class Node {
|
||||
|
||||
isRoot = () => this._isRoot;
|
||||
|
||||
get isRootNode () {
|
||||
return this._isRoot;
|
||||
};
|
||||
|
||||
// componentMeta() {
|
||||
// return this.componentMeta;
|
||||
// }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user