Skip to content

Commit d3c891e

Browse files
authored
feat: support for NotFoundComponent design state is optional (alibaba#1013)
1 parent 438cccd commit d3c891e

File tree

10 files changed

+78
-31
lines changed

10 files changed

+78
-31
lines changed

packages/designer/src/builtin-simulator/host.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
232232
return engineConfig.get('thisRequiredInJSE') ?? true;
233233
}
234234

235+
get enableStrictNotFoundMode(): any {
236+
return engineConfig.get('enableStrictNotFoundMode') ?? false;
237+
}
238+
235239
@computed get componentsAsset(): Asset | undefined {
236240
return this.get('componentsAsset');
237241
}

packages/designer/src/component-meta.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,29 @@ export class ComponentMeta {
176176
}
177177

178178
private parseMetadata(metadata: ComponentMetadata) {
179-
const { componentName, npm } = metadata;
179+
const { componentName, npm, ...others } = metadata;
180+
let _metadata = metadata;
181+
if (!npm && !Object.keys(others).length) {
182+
// 没有注册的组件,只能删除,不支持复制、移动等操作
183+
_metadata = {
184+
componentName,
185+
configure: {
186+
component: {
187+
disableBehaviors: ['copy', 'move', 'lock', 'unlock'],
188+
},
189+
advanced: {
190+
callbacks: {
191+
onMoveHook: () => false,
192+
},
193+
},
194+
},
195+
};
196+
}
180197
this._npm = npm || this._npm;
181198
this._componentName = componentName;
182199

183200
// 额外转换逻辑
184-
this._transformedMetadata = this.transformMetadata(metadata);
201+
this._transformedMetadata = this.transformMetadata(_metadata);
185202

186203
const { title } = this._transformedMetadata;
187204
if (title) {

packages/designer/tests/builtin-simulator/host.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
setShaken,
2424
} from '../../src/designer/dragon';
2525
import { Project } from '../../src/project/project';
26+
import pageMetadata from '../fixtures/component-metadata/page';
2627
import { Node } from '../../src/document/node/node';
2728
import { Designer } from '../../src/designer/designer';
2829
import { DocumentModel } from '../../src/document/document-model';
@@ -46,6 +47,7 @@ describe('Host 测试', () => {
4647
beforeEach(() => {
4748
designer = new Designer({ editor });
4849
project = designer.project;
50+
designer.createComponentMeta(pageMetadata);
4951
doc = project.createDocument(formSchema);
5052
host = new BuiltinSimulatorHost(designer.project);
5153
});
@@ -373,6 +375,14 @@ describe('Host 测试', () => {
373375
},
374376
})).toBeNull();
375377
});
378+
it('notFoundComponent', () => {
379+
expect(host.locate({
380+
dragObject: {
381+
type: DragObjectType.Node,
382+
nodes: [doc.getNode('form')],
383+
},
384+
})).toBeUndefined();
385+
})
376386
it('locate', () => {
377387
host.locate({
378388
dragObject: {

packages/editor-core/src/config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ const VALID_ENGINE_OPTIONS = {
137137
type: 'boolean',
138138
description: 'JSExpression 是否只支持使用 this 来访问上下文变量',
139139
},
140+
enableStrictNotFoundMode: {
141+
type: 'boolean',
142+
description: '当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件',
143+
},
140144
};
141145
export interface EngineOptions {
142146
/**
@@ -258,6 +262,12 @@ export interface EngineOptions {
258262
* JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false
259263
*/
260264
thisRequiredInJSE?: boolean;
265+
266+
/**
267+
* @default false
268+
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
269+
*/
270+
enableStrictNotFoundMode?: boolean;
261271
}
262272

263273
const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => {

packages/react-simulator-renderer/src/renderer-view.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ class Renderer extends Component<{
255255
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
256256
documentInstance.mountInstance(schema.id, ref);
257257
}}
258+
enableStrictNotFoundMode={host.enableStrictNotFoundMode}
258259
/>
259260
);
260261
}

packages/react-simulator-renderer/test/src/renderer/__snapshots__/demo.test.tsx.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ exports[`Base should be render NotFoundComponent 1`] = `
1111
<div
1212
componentName="Text"
1313
>
14-
Component Not Found
14+
Text Component Not Found
1515
</div>
1616
</div>
1717
</div>

packages/renderer-core/src/adapter/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,21 @@ class Adapter {
2121
}
2222

2323
initRuntime() {
24-
const Component: IGeneralConstructor = class {
24+
const Component: IGeneralConstructor = class <T = any, S = any> {
2525
setState() {}
2626
forceUpdate() {}
2727
render() {}
28-
state: Record<string, unknown>;
29-
props: Record<string, unknown>;
28+
state: Readonly<S>;
29+
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
3030
refs: Record<string, unknown>;
3131
context: Record<string, unknown>;
3232
};
33-
const PureComponent: IGeneralConstructor = class {
33+
const PureComponent = class <T = any, S = any> {
3434
setState() {}
3535
forceUpdate() {}
3636
render() {}
37-
state: Record<string, unknown>;
38-
props: Record<string, unknown>;
37+
state: Readonly<S>;
38+
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
3939
refs: Record<string, unknown>;
4040
context: Record<string, unknown>;
4141
};

packages/renderer-core/src/renderer/base.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
104104
return customBaseRenderer;
105105
}
106106

107-
const runtime = adapter.getRuntime();
108-
const Component = runtime.Component as IGeneralConstructor<
109-
IBaseRendererProps,
110-
Record<string, any>,
111-
any
112-
>;
113-
const { createElement } = runtime;
107+
const { Component, createElement } = adapter.getRuntime();
114108
const Div = divFactory();
115109
const VisualDom = visualDomFactory();
116110
const AppContext = contextFactory();
@@ -125,7 +119,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
125119
const DEFAULT_LOOP_ARG_INDEX = 'index';
126120
let scopeIdx = 0;
127121

128-
return class BaseRenderer extends Component {
122+
return class BaseRenderer extends Component<IBaseRendererProps, Record<string, any>> {
129123
static displayName = 'BaseRenderer';
130124

131125
static defaultProps = {
@@ -533,6 +527,10 @@ export default function baseRendererFactory(): IBaseRenderComponent {
533527
{
534528
componentName: schema.componentName,
535529
componentId: schema.id,
530+
enableStrictNotFoundMode: engine.props.enableStrictNotFoundMode,
531+
ref: (ref: any) => {
532+
ref && engine.props?.onCompGetRef(schema, ref);
533+
},
536534
},
537535
this.__getSchemaChildrenVirtualDom(schema, scope, Comp),
538536
);

packages/renderer-core/src/renderer/renderer.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ import contextFactory from '../context';
44
import { isFileSchema, isEmpty } from '../utils';
55
import baseRendererFactory from './base';
66
import divFactory from '../components/Div';
7-
import { IGeneralConstructor, IRenderComponent, IRendererProps, IRendererState } from '../types';
8-
import { RootSchema } from '@alilc/lowcode-types';
7+
import { IRenderComponent, IRendererProps, IRendererState } from '../types';
8+
import { NodeSchema, RootSchema } from '@alilc/lowcode-types';
99

1010
export default function rendererFactory(): IRenderComponent {
11-
const runtime = adapter.getRuntime();
12-
const Component = runtime.Component as IGeneralConstructor<IRendererProps, Record<string, any>>;
13-
const PureComponent = runtime.PureComponent as IGeneralConstructor<IRendererProps, Record<string, any>>;
14-
const { createElement, findDOMNode } = runtime;
11+
const { PureComponent, Component, createElement, findDOMNode } = adapter.getRuntime();
1512
const RENDERER_COMPS: any = adapter.getRenderers();
1613
const BaseRenderer = baseRendererFactory();
1714
const AppContext = contextFactory();
@@ -21,7 +18,7 @@ export default function rendererFactory(): IRenderComponent {
2118

2219
const debug = Debug('renderer:entry');
2320

24-
class FaultComponent extends PureComponent {
21+
class FaultComponent extends PureComponent<NodeSchema> {
2522
render() {
2623
// FIXME: errorlog
2724
console.error('render error', this.props);
@@ -35,17 +32,22 @@ export default function rendererFactory(): IRenderComponent {
3532
color: '#ff0000',
3633
border: '2px solid #ff0000',
3734
},
38-
}, '组件渲染异常,请查看控制台日志');
35+
}, `${this.props.componentName || ''} 组件渲染异常,请查看控制台日志`);
3936
}
4037
}
4138

42-
class NotFoundComponent extends PureComponent {
39+
class NotFoundComponent extends PureComponent<{
40+
componentName: string;
41+
} & IRendererProps> {
4342
render() {
44-
return createElement(Div, this.props, this.props.children || 'Component Not Found');
43+
if (this.props.enableStrictNotFoundMode) {
44+
return `${this.props.componentName || ''} Component Not Found`;
45+
}
46+
return createElement(Div, this.props, this.props.children || `${this.props.componentName || ''} Component Not Found`);
4547
}
4648
}
4749

48-
return class Renderer extends Component {
50+
return class Renderer extends Component<IRendererProps> {
4951
static displayName = 'Renderer';
5052

5153
state: Partial<IRendererState> = {};

packages/renderer-core/src/types/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ interface IGeneralComponent<P = {}, S = {}, SS = any> extends ComponentLifecycle
2121
}
2222

2323
export type IGeneralConstructor<
24-
P = {
24+
T = {
2525
[key: string]: any;
2626
}, S = {
2727
[key: string]: any;
28-
}, SS = any
29-
> = new (props: any, context: any) => IGeneralComponent<P, S, SS>;
28+
}, D = any
29+
> = new <TT = T, SS = S, DD = D>(props: TT, context: any) => IGeneralComponent<TT, SS, DD>;
3030

3131
/**
3232
* duck-typed History
@@ -133,6 +133,11 @@ export interface IRendererProps {
133133
* JSExpression 是否只支持使用 this 来访问上下文变量
134134
*/
135135
thisRequiredInJSE?: boolean;
136+
/**
137+
* @default false
138+
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
139+
*/
140+
enableStrictNotFoundMode?: boolean;
136141
}
137142

138143
export interface IRendererState {

0 commit comments

Comments
 (0)