mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-11 18:42:56 +00:00
feat: support for NotFoundComponent design state is optional (#1013)
This commit is contained in:
parent
438cccd58e
commit
d3c891e2a4
@ -232,6 +232,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
||||
return engineConfig.get('thisRequiredInJSE') ?? true;
|
||||
}
|
||||
|
||||
get enableStrictNotFoundMode(): any {
|
||||
return engineConfig.get('enableStrictNotFoundMode') ?? false;
|
||||
}
|
||||
|
||||
@computed get componentsAsset(): Asset | undefined {
|
||||
return this.get('componentsAsset');
|
||||
}
|
||||
|
||||
@ -176,12 +176,29 @@ export class ComponentMeta {
|
||||
}
|
||||
|
||||
private parseMetadata(metadata: ComponentMetadata) {
|
||||
const { componentName, npm } = metadata;
|
||||
const { componentName, npm, ...others } = metadata;
|
||||
let _metadata = metadata;
|
||||
if (!npm && !Object.keys(others).length) {
|
||||
// 没有注册的组件,只能删除,不支持复制、移动等操作
|
||||
_metadata = {
|
||||
componentName,
|
||||
configure: {
|
||||
component: {
|
||||
disableBehaviors: ['copy', 'move', 'lock', 'unlock'],
|
||||
},
|
||||
advanced: {
|
||||
callbacks: {
|
||||
onMoveHook: () => false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
this._npm = npm || this._npm;
|
||||
this._componentName = componentName;
|
||||
|
||||
// 额外转换逻辑
|
||||
this._transformedMetadata = this.transformMetadata(metadata);
|
||||
this._transformedMetadata = this.transformMetadata(_metadata);
|
||||
|
||||
const { title } = this._transformedMetadata;
|
||||
if (title) {
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
setShaken,
|
||||
} from '../../src/designer/dragon';
|
||||
import { Project } from '../../src/project/project';
|
||||
import pageMetadata from '../fixtures/component-metadata/page';
|
||||
import { Node } from '../../src/document/node/node';
|
||||
import { Designer } from '../../src/designer/designer';
|
||||
import { DocumentModel } from '../../src/document/document-model';
|
||||
@ -46,6 +47,7 @@ describe('Host 测试', () => {
|
||||
beforeEach(() => {
|
||||
designer = new Designer({ editor });
|
||||
project = designer.project;
|
||||
designer.createComponentMeta(pageMetadata);
|
||||
doc = project.createDocument(formSchema);
|
||||
host = new BuiltinSimulatorHost(designer.project);
|
||||
});
|
||||
@ -373,6 +375,14 @@ describe('Host 测试', () => {
|
||||
},
|
||||
})).toBeNull();
|
||||
});
|
||||
it('notFoundComponent', () => {
|
||||
expect(host.locate({
|
||||
dragObject: {
|
||||
type: DragObjectType.Node,
|
||||
nodes: [doc.getNode('form')],
|
||||
},
|
||||
})).toBeUndefined();
|
||||
})
|
||||
it('locate', () => {
|
||||
host.locate({
|
||||
dragObject: {
|
||||
|
||||
@ -137,6 +137,10 @@ const VALID_ENGINE_OPTIONS = {
|
||||
type: 'boolean',
|
||||
description: 'JSExpression 是否只支持使用 this 来访问上下文变量',
|
||||
},
|
||||
enableStrictNotFoundMode: {
|
||||
type: 'boolean',
|
||||
description: '当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件',
|
||||
},
|
||||
};
|
||||
export interface EngineOptions {
|
||||
/**
|
||||
@ -258,6 +262,12 @@ export interface EngineOptions {
|
||||
* JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false
|
||||
*/
|
||||
thisRequiredInJSE?: boolean;
|
||||
|
||||
/**
|
||||
* @default false
|
||||
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
|
||||
*/
|
||||
enableStrictNotFoundMode?: boolean;
|
||||
}
|
||||
|
||||
const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => {
|
||||
|
||||
@ -255,6 +255,7 @@ class Renderer extends Component<{
|
||||
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
||||
documentInstance.mountInstance(schema.id, ref);
|
||||
}}
|
||||
enableStrictNotFoundMode={host.enableStrictNotFoundMode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ exports[`Base should be render NotFoundComponent 1`] = `
|
||||
<div
|
||||
componentName="Text"
|
||||
>
|
||||
Component Not Found
|
||||
Text Component Not Found
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -21,21 +21,21 @@ class Adapter {
|
||||
}
|
||||
|
||||
initRuntime() {
|
||||
const Component: IGeneralConstructor = class {
|
||||
const Component: IGeneralConstructor = class <T = any, S = any> {
|
||||
setState() {}
|
||||
forceUpdate() {}
|
||||
render() {}
|
||||
state: Record<string, unknown>;
|
||||
props: Record<string, unknown>;
|
||||
state: Readonly<S>;
|
||||
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
|
||||
refs: Record<string, unknown>;
|
||||
context: Record<string, unknown>;
|
||||
};
|
||||
const PureComponent: IGeneralConstructor = class {
|
||||
const PureComponent = class <T = any, S = any> {
|
||||
setState() {}
|
||||
forceUpdate() {}
|
||||
render() {}
|
||||
state: Record<string, unknown>;
|
||||
props: Record<string, unknown>;
|
||||
state: Readonly<S>;
|
||||
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
|
||||
refs: Record<string, unknown>;
|
||||
context: Record<string, unknown>;
|
||||
};
|
||||
|
||||
@ -104,13 +104,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
return customBaseRenderer;
|
||||
}
|
||||
|
||||
const runtime = adapter.getRuntime();
|
||||
const Component = runtime.Component as IGeneralConstructor<
|
||||
IBaseRendererProps,
|
||||
Record<string, any>,
|
||||
any
|
||||
>;
|
||||
const { createElement } = runtime;
|
||||
const { Component, createElement } = adapter.getRuntime();
|
||||
const Div = divFactory();
|
||||
const VisualDom = visualDomFactory();
|
||||
const AppContext = contextFactory();
|
||||
@ -125,7 +119,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
const DEFAULT_LOOP_ARG_INDEX = 'index';
|
||||
let scopeIdx = 0;
|
||||
|
||||
return class BaseRenderer extends Component {
|
||||
return class BaseRenderer extends Component<IBaseRendererProps, Record<string, any>> {
|
||||
static displayName = 'BaseRenderer';
|
||||
|
||||
static defaultProps = {
|
||||
@ -533,6 +527,10 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
||||
{
|
||||
componentName: schema.componentName,
|
||||
componentId: schema.id,
|
||||
enableStrictNotFoundMode: engine.props.enableStrictNotFoundMode,
|
||||
ref: (ref: any) => {
|
||||
ref && engine.props?.onCompGetRef(schema, ref);
|
||||
},
|
||||
},
|
||||
this.__getSchemaChildrenVirtualDom(schema, scope, Comp),
|
||||
);
|
||||
|
||||
@ -4,14 +4,11 @@ import contextFactory from '../context';
|
||||
import { isFileSchema, isEmpty } from '../utils';
|
||||
import baseRendererFactory from './base';
|
||||
import divFactory from '../components/Div';
|
||||
import { IGeneralConstructor, IRenderComponent, IRendererProps, IRendererState } from '../types';
|
||||
import { RootSchema } from '@alilc/lowcode-types';
|
||||
import { IRenderComponent, IRendererProps, IRendererState } from '../types';
|
||||
import { NodeSchema, RootSchema } from '@alilc/lowcode-types';
|
||||
|
||||
export default function rendererFactory(): IRenderComponent {
|
||||
const runtime = adapter.getRuntime();
|
||||
const Component = runtime.Component as IGeneralConstructor<IRendererProps, Record<string, any>>;
|
||||
const PureComponent = runtime.PureComponent as IGeneralConstructor<IRendererProps, Record<string, any>>;
|
||||
const { createElement, findDOMNode } = runtime;
|
||||
const { PureComponent, Component, createElement, findDOMNode } = adapter.getRuntime();
|
||||
const RENDERER_COMPS: any = adapter.getRenderers();
|
||||
const BaseRenderer = baseRendererFactory();
|
||||
const AppContext = contextFactory();
|
||||
@ -21,7 +18,7 @@ export default function rendererFactory(): IRenderComponent {
|
||||
|
||||
const debug = Debug('renderer:entry');
|
||||
|
||||
class FaultComponent extends PureComponent {
|
||||
class FaultComponent extends PureComponent<NodeSchema> {
|
||||
render() {
|
||||
// FIXME: errorlog
|
||||
console.error('render error', this.props);
|
||||
@ -35,17 +32,22 @@ export default function rendererFactory(): IRenderComponent {
|
||||
color: '#ff0000',
|
||||
border: '2px solid #ff0000',
|
||||
},
|
||||
}, '组件渲染异常,请查看控制台日志');
|
||||
}, `${this.props.componentName || ''} 组件渲染异常,请查看控制台日志`);
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundComponent extends PureComponent {
|
||||
class NotFoundComponent extends PureComponent<{
|
||||
componentName: string;
|
||||
} & IRendererProps> {
|
||||
render() {
|
||||
return createElement(Div, this.props, this.props.children || 'Component Not Found');
|
||||
if (this.props.enableStrictNotFoundMode) {
|
||||
return `${this.props.componentName || ''} Component Not Found`;
|
||||
}
|
||||
return createElement(Div, this.props, this.props.children || `${this.props.componentName || ''} Component Not Found`);
|
||||
}
|
||||
}
|
||||
|
||||
return class Renderer extends Component {
|
||||
return class Renderer extends Component<IRendererProps> {
|
||||
static displayName = 'Renderer';
|
||||
|
||||
state: Partial<IRendererState> = {};
|
||||
|
||||
@ -21,12 +21,12 @@ interface IGeneralComponent<P = {}, S = {}, SS = any> extends ComponentLifecycle
|
||||
}
|
||||
|
||||
export type IGeneralConstructor<
|
||||
P = {
|
||||
T = {
|
||||
[key: string]: any;
|
||||
}, S = {
|
||||
[key: string]: any;
|
||||
}, SS = any
|
||||
> = new (props: any, context: any) => IGeneralComponent<P, S, SS>;
|
||||
}, D = any
|
||||
> = new <TT = T, SS = S, DD = D>(props: TT, context: any) => IGeneralComponent<TT, SS, DD>;
|
||||
|
||||
/**
|
||||
* duck-typed History
|
||||
@ -133,6 +133,11 @@ export interface IRendererProps {
|
||||
* JSExpression 是否只支持使用 this 来访问上下文变量
|
||||
*/
|
||||
thisRequiredInJSE?: boolean;
|
||||
/**
|
||||
* @default false
|
||||
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
|
||||
*/
|
||||
enableStrictNotFoundMode?: boolean;
|
||||
}
|
||||
|
||||
export interface IRendererState {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user