@chamn/render 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commonComponent/index.d.ts +12 -0
- package/dist/const/index.d.ts +2 -0
- package/dist/core/ReactErrorBoundary.d.ts +26 -0
- package/dist/core/adapter.d.ts +64 -0
- package/dist/core/adapterReact.d.ts +108 -0
- package/dist/core/designReactRender.d.ts +47 -0
- package/dist/core/refManager.d.ts +7 -0
- package/dist/core/render.d.ts +32 -0
- package/dist/core/storeManager.d.ts +11 -0
- package/dist/core/type.d.ts +9 -0
- package/dist/{index.cjs.js → index.js} +2 -2
- package/dist/index.js.map +1 -0
- package/dist/{index.es.js → index.mjs} +94 -83
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/util/assetsLoader.d.ts +15 -0
- package/dist/util/index.d.ts +20 -0
- package/package.json +14 -9
- package/.eslintignore +0 -1
- package/.eslintrc.js +0 -30
- package/.prettierrc.json +0 -7
- package/CHANGELOG.md +0 -40
- package/__tests__/demo.test.ts +0 -3
- package/build.config.ts +0 -20
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.es.js.map +0 -1
- package/index.html +0 -16
- package/jest.config.js +0 -196
- package/public/vite.svg +0 -1
- package/src/_dev_/components.tsx +0 -12
- package/src/_dev_/dev.tsx +0 -12
- package/src/_dev_/index.css +0 -13
- package/src/_dev_/page/DesignerRenderDemo.tsx +0 -65
- package/src/_dev_/page/RenderDemo.tsx +0 -60
- package/src/_dev_/router.tsx +0 -15
- package/src/commonComponent/index.tsx +0 -184
- package/src/const/index.ts +0 -5
- package/src/core/ReactErrorBoundary.ts +0 -91
- package/src/core/adapter.ts +0 -133
- package/src/core/adapterReact.ts +0 -734
- package/src/core/designReactRender.ts +0 -325
- package/src/core/refManager.ts +0 -18
- package/src/core/render.ts +0 -123
- package/src/core/storeManager.ts +0 -57
- package/src/core/type.ts +0 -10
- package/src/util/assetsLoader.ts +0 -73
- package/src/util/index.ts +0 -164
- package/src/vite-env.d.ts +0 -1
- package/stats.html +0 -6177
- package/tsconfig.json +0 -26
- /package/{src/index.ts → dist/index.d.ts} +0 -0
package/src/core/adapterReact.ts
DELETED
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
CNode,
|
|
4
|
-
CPage,
|
|
5
|
-
CProp,
|
|
6
|
-
CPropDataType,
|
|
7
|
-
CRootNode,
|
|
8
|
-
FunctionPropType,
|
|
9
|
-
getRandomStr,
|
|
10
|
-
InnerComponentNameEnum,
|
|
11
|
-
isExpression,
|
|
12
|
-
isFunction,
|
|
13
|
-
isNodeModel,
|
|
14
|
-
isPropModel,
|
|
15
|
-
isSlotModel,
|
|
16
|
-
JSExpressionPropType,
|
|
17
|
-
} from '@chamn/model';
|
|
18
|
-
import { AdapterOptionType, ContextType, getAdapter } from './adapter';
|
|
19
|
-
import { isArray, isPlainObject } from 'lodash-es';
|
|
20
|
-
import {
|
|
21
|
-
canAcceptsRef,
|
|
22
|
-
compWrapper,
|
|
23
|
-
convertCodeStringToFunction,
|
|
24
|
-
formatSourceStylePropertyName,
|
|
25
|
-
getCSSTextValue,
|
|
26
|
-
getObjFromArrayMap,
|
|
27
|
-
runExpression,
|
|
28
|
-
shouldConstruct,
|
|
29
|
-
} from '../util';
|
|
30
|
-
import { DYNAMIC_COMPONENT_TYPE, InnerPropList } from '../const';
|
|
31
|
-
import { StoreApi } from 'zustand/vanilla';
|
|
32
|
-
import { StoreManager } from './storeManager';
|
|
33
|
-
|
|
34
|
-
export class DefineReactAdapter {
|
|
35
|
-
renderMode: AdapterOptionType['renderMode'] = 'normal';
|
|
36
|
-
components: AdapterOptionType['components'] = {};
|
|
37
|
-
storeManager = new StoreManager();
|
|
38
|
-
runtimeComponentCache = new Map();
|
|
39
|
-
onGetRef?: AdapterOptionType['onGetRef'];
|
|
40
|
-
onGetComponent: AdapterOptionType['onGetComponent'];
|
|
41
|
-
onComponentMount: AdapterOptionType['onComponentMount'];
|
|
42
|
-
|
|
43
|
-
onComponentDestroy: AdapterOptionType['onComponentDestroy'];
|
|
44
|
-
|
|
45
|
-
// 处理 props 钩子
|
|
46
|
-
processNodeConfigHook?: AdapterOptionType['processNodeConfigHook'];
|
|
47
|
-
getComponent(currentNode: CNode | CRootNode) {
|
|
48
|
-
const componentName = currentNode.value.componentName;
|
|
49
|
-
let res: any = this.components[componentName] || (() => `Component [${componentName}] not found`);
|
|
50
|
-
// check component can accept ref
|
|
51
|
-
if (!canAcceptsRef(res)) {
|
|
52
|
-
res = compWrapper(res);
|
|
53
|
-
this.components[componentName] = res;
|
|
54
|
-
}
|
|
55
|
-
// 定制钩子
|
|
56
|
-
if (this.onGetComponent) {
|
|
57
|
-
res = this.onGetComponent?.(res, currentNode);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return res;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
getContext(data: ContextType = {}, ctx?: ContextType | null): ContextType {
|
|
64
|
-
let newCtx: ContextType = data;
|
|
65
|
-
if (ctx) {
|
|
66
|
-
newCtx = {
|
|
67
|
-
...data,
|
|
68
|
-
};
|
|
69
|
-
(newCtx as any).__proto__ = ctx || null;
|
|
70
|
-
}
|
|
71
|
-
return newCtx;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
pageRender(
|
|
75
|
-
pageModel: CPage,
|
|
76
|
-
{
|
|
77
|
-
components,
|
|
78
|
-
onGetRef,
|
|
79
|
-
$$context = {},
|
|
80
|
-
onGetComponent,
|
|
81
|
-
onComponentMount,
|
|
82
|
-
onComponentDestroy,
|
|
83
|
-
renderMode,
|
|
84
|
-
processNodeConfigHook,
|
|
85
|
-
}: AdapterOptionType
|
|
86
|
-
) {
|
|
87
|
-
this.renderMode = renderMode;
|
|
88
|
-
this.components = components;
|
|
89
|
-
this.onGetRef = onGetRef;
|
|
90
|
-
this.onGetComponent = onGetComponent;
|
|
91
|
-
this.onComponentMount = onComponentMount;
|
|
92
|
-
this.onComponentDestroy = onComponentDestroy;
|
|
93
|
-
this.processNodeConfigHook = processNodeConfigHook;
|
|
94
|
-
|
|
95
|
-
//做一些全局 store 操作
|
|
96
|
-
const rootNode = pageModel.value.componentsTree;
|
|
97
|
-
const component = this.getComponent(rootNode);
|
|
98
|
-
|
|
99
|
-
const newComp = this.convertModelToComponent(component, pageModel.value.componentsTree);
|
|
100
|
-
|
|
101
|
-
const props: Record<string, any> = {};
|
|
102
|
-
const propsModel = rootNode.props;
|
|
103
|
-
Object.keys(propsModel).forEach((key) => {
|
|
104
|
-
props[key] = propsModel[key].value;
|
|
105
|
-
});
|
|
106
|
-
props.$$context = $$context;
|
|
107
|
-
return this.render(newComp, props);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
transformProps(
|
|
111
|
-
originalProps: Record<string, any> = {},
|
|
112
|
-
{
|
|
113
|
-
$$context: parentContext,
|
|
114
|
-
}: {
|
|
115
|
-
$$context: ContextType;
|
|
116
|
-
}
|
|
117
|
-
) {
|
|
118
|
-
const propsModel = originalProps;
|
|
119
|
-
const handlePropVal: (propVal: CPropDataType) => Record<string, any> = (propVal: CPropDataType) => {
|
|
120
|
-
if (Array.isArray(propVal)) {
|
|
121
|
-
return propVal.map((it) => handlePropVal(it));
|
|
122
|
-
} else if (isPropModel(propVal)) {
|
|
123
|
-
return handlePropVal(propVal.value);
|
|
124
|
-
} else if (isSlotModel(propVal)) {
|
|
125
|
-
const slotProp = propVal.value;
|
|
126
|
-
const tempVal = slotProp.value;
|
|
127
|
-
if (!tempVal) {
|
|
128
|
-
console.warn('slot value is null, this maybe cause some error, pls check it', originalProps);
|
|
129
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
130
|
-
return () => {};
|
|
131
|
-
}
|
|
132
|
-
const handleSingleSlot = (it: CNode) => {
|
|
133
|
-
const key = `${it.id}-${DYNAMIC_COMPONENT_TYPE}`;
|
|
134
|
-
|
|
135
|
-
// 复用
|
|
136
|
-
if (this.runtimeComponentCache.get(it.id)) {
|
|
137
|
-
return {
|
|
138
|
-
key: key,
|
|
139
|
-
component: this.runtimeComponentCache.get(it.id),
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
const component = this.getComponent(it);
|
|
143
|
-
const PropNodeRender = this.convertModelToComponent(component, it);
|
|
144
|
-
const parmaList = slotProp.params || [];
|
|
145
|
-
// 运行时组件函数
|
|
146
|
-
const PropNodeFuncWrap = (...args: any) => {
|
|
147
|
-
const params: Record<any, any> = getObjFromArrayMap(args, parmaList);
|
|
148
|
-
const $$context = this.getContext(
|
|
149
|
-
{
|
|
150
|
-
params,
|
|
151
|
-
},
|
|
152
|
-
parentContext
|
|
153
|
-
);
|
|
154
|
-
return this.render(PropNodeRender, {
|
|
155
|
-
$$context,
|
|
156
|
-
key,
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
const res = {
|
|
160
|
-
component: PropNodeFuncWrap,
|
|
161
|
-
key,
|
|
162
|
-
};
|
|
163
|
-
return res;
|
|
164
|
-
};
|
|
165
|
-
if (Array.isArray(tempVal)) {
|
|
166
|
-
const renderList = tempVal?.map((it: any) => {
|
|
167
|
-
return handleSingleSlot(it);
|
|
168
|
-
});
|
|
169
|
-
// TODO: 需要做额外的处理
|
|
170
|
-
return (...args: any[]) => {
|
|
171
|
-
return renderList.map((renderItem) => {
|
|
172
|
-
const isClassComponent = shouldConstruct(renderItem.component);
|
|
173
|
-
|
|
174
|
-
if (isClassComponent) {
|
|
175
|
-
return React.createElement(renderItem.component, {
|
|
176
|
-
$$context: parentContext,
|
|
177
|
-
key: renderItem.key,
|
|
178
|
-
});
|
|
179
|
-
} else {
|
|
180
|
-
return renderItem.component(...args);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
} else {
|
|
185
|
-
return handleSingleSlot(tempVal).component;
|
|
186
|
-
}
|
|
187
|
-
} else if (isExpression(propVal)) {
|
|
188
|
-
const expProp = propVal as JSExpressionPropType;
|
|
189
|
-
const newVal = runExpression(expProp.value, parentContext || {});
|
|
190
|
-
return newVal;
|
|
191
|
-
} else if (isFunction(propVal)) {
|
|
192
|
-
const funcProp = propVal as FunctionPropType;
|
|
193
|
-
return convertCodeStringToFunction(funcProp.value, parentContext, this.storeManager);
|
|
194
|
-
} else if (isPlainObject(propVal)) {
|
|
195
|
-
// 可能是 普通的 props 模型
|
|
196
|
-
let specialPropVal = propVal;
|
|
197
|
-
if (isPropModel(propVal)) {
|
|
198
|
-
specialPropVal = (propVal as CProp).value;
|
|
199
|
-
}
|
|
200
|
-
const objPropVal = specialPropVal as Record<string, any>;
|
|
201
|
-
const newVal: Record<string, any> = {};
|
|
202
|
-
Object.keys(specialPropVal).forEach((k) => {
|
|
203
|
-
newVal[k] = handlePropVal(objPropVal[k]);
|
|
204
|
-
});
|
|
205
|
-
return newVal;
|
|
206
|
-
} else {
|
|
207
|
-
return propVal;
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
const newProps: Record<string, any> = {};
|
|
211
|
-
Object.keys(propsModel).forEach((propKey) => {
|
|
212
|
-
const propVal = propsModel[propKey];
|
|
213
|
-
newProps[propKey] = handlePropVal(propVal);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
return newProps;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
collectSpecialProps(originalProps: Record<string, unknown> = {}, isValidate: (val: unknown) => boolean) {
|
|
220
|
-
const res: { keyPath: string[]; val: any }[] = [];
|
|
221
|
-
const cb = (keyPath: string[], val: Record<string, any>) => {
|
|
222
|
-
let tempVal: any = val;
|
|
223
|
-
if (isPropModel(val)) {
|
|
224
|
-
tempVal = val.value;
|
|
225
|
-
}
|
|
226
|
-
if (isValidate(tempVal)) {
|
|
227
|
-
res.push({
|
|
228
|
-
keyPath,
|
|
229
|
-
val: tempVal,
|
|
230
|
-
});
|
|
231
|
-
} else if (isArray(tempVal)) {
|
|
232
|
-
tempVal.forEach((it, index) => {
|
|
233
|
-
cb([...keyPath, String(index)], it);
|
|
234
|
-
});
|
|
235
|
-
} else if (isPlainObject(tempVal)) {
|
|
236
|
-
Object.keys(tempVal).forEach((key) => {
|
|
237
|
-
cb([...keyPath, key], tempVal[key]);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
cb(['$root'], originalProps);
|
|
243
|
-
return res;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
convertModelToComponent(originalComponent: any, nodeModel: CNode | CRootNode) {
|
|
247
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
248
|
-
const that = this;
|
|
249
|
-
type PropsType = {
|
|
250
|
-
$$context: ContextType;
|
|
251
|
-
$$nodeModel: CNode | CRootNode;
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
class DynamicComponent extends React.Component<PropsType> {
|
|
255
|
-
static __CP_TYPE__ = DYNAMIC_COMPONENT_TYPE;
|
|
256
|
-
_CONDITION = true;
|
|
257
|
-
_DESIGN_BOX = false;
|
|
258
|
-
_NODE_MODEL = nodeModel;
|
|
259
|
-
_NODE_ID = nodeModel.id;
|
|
260
|
-
|
|
261
|
-
UNIQUE_ID = `${nodeModel.id}_${getRandomStr()}`;
|
|
262
|
-
targetComponentRef: React.MutableRefObject<any>;
|
|
263
|
-
listenerHandle: (() => void)[] = [];
|
|
264
|
-
storeState: StoreApi<any>;
|
|
265
|
-
// not react data
|
|
266
|
-
staticState: Record<string, any> = {};
|
|
267
|
-
storeListenDisposeLint: (() => void)[] = [];
|
|
268
|
-
// save dom and media css
|
|
269
|
-
domHeader: HTMLHeadElement | undefined;
|
|
270
|
-
mediaStyleDomMap: Record<string, HTMLStyleElement> = {};
|
|
271
|
-
|
|
272
|
-
constructor(props: PropsType) {
|
|
273
|
-
super(props);
|
|
274
|
-
this.targetComponentRef = React.createRef();
|
|
275
|
-
this.state = nodeModel.value.state || {};
|
|
276
|
-
const storeName = nodeModel.value.stateName || nodeModel.id;
|
|
277
|
-
|
|
278
|
-
const nodeStore = that.storeManager.getStore(storeName);
|
|
279
|
-
if (!nodeStore) {
|
|
280
|
-
// add to global store manager
|
|
281
|
-
this.storeState = that.storeManager.addStore(storeName, () => {
|
|
282
|
-
return {
|
|
283
|
-
...(nodeModel.value.state || {}),
|
|
284
|
-
};
|
|
285
|
-
});
|
|
286
|
-
} else {
|
|
287
|
-
this.storeState = nodeStore;
|
|
288
|
-
nodeStore.setState({
|
|
289
|
-
...(nodeModel.value.state || {}),
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// sync storeState to component state;
|
|
294
|
-
this.storeState.subscribe((newState) => {
|
|
295
|
-
this.setState({
|
|
296
|
-
...newState,
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
this.connectStore();
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
updateState = (newState: any) => {
|
|
303
|
-
this.storeState.setState(newState);
|
|
304
|
-
this.forceUpdate();
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
connectStore() {
|
|
308
|
-
// props
|
|
309
|
-
const expressionList = that.collectSpecialProps(nodeModel.props, (val) => {
|
|
310
|
-
if (isExpression(val)) {
|
|
311
|
-
return true;
|
|
312
|
-
} else {
|
|
313
|
-
return false;
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
// TODO: css props、classNames props
|
|
318
|
-
const cssAndClassExpressionList = that.collectSpecialProps(
|
|
319
|
-
{
|
|
320
|
-
css: nodeModel.value.css,
|
|
321
|
-
class: nodeModel.value.classNames,
|
|
322
|
-
},
|
|
323
|
-
(val) => {
|
|
324
|
-
if (isExpression(val)) {
|
|
325
|
-
return true;
|
|
326
|
-
} else {
|
|
327
|
-
return false;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
|
|
332
|
-
const list = [...expressionList, ...cssAndClassExpressionList]
|
|
333
|
-
.map((el) => {
|
|
334
|
-
const targetVal: JSExpressionPropType = el.val;
|
|
335
|
-
const reg = /\$\$context.stateManager\.(.+?)\./gim;
|
|
336
|
-
const res = reg.exec(targetVal.value);
|
|
337
|
-
if (res?.length) {
|
|
338
|
-
return res[1];
|
|
339
|
-
} else {
|
|
340
|
-
return '';
|
|
341
|
-
}
|
|
342
|
-
})
|
|
343
|
-
.filter(Boolean);
|
|
344
|
-
const uniqueList = Array.from(new Set(list));
|
|
345
|
-
// TODO: list need now repeat
|
|
346
|
-
const disposeList: (() => void)[] = [];
|
|
347
|
-
if (uniqueList.length) {
|
|
348
|
-
uniqueList.forEach((storeName) => {
|
|
349
|
-
const store = that.storeManager.getStore(storeName);
|
|
350
|
-
if (!store) {
|
|
351
|
-
that.storeManager.addStore(storeName, () => {
|
|
352
|
-
return {};
|
|
353
|
-
});
|
|
354
|
-
console.log(that.storeManager, storeName, 'not exits');
|
|
355
|
-
}
|
|
356
|
-
const handle = that.storeManager.connect(storeName, () => {
|
|
357
|
-
this.forceUpdate();
|
|
358
|
-
});
|
|
359
|
-
disposeList.push(handle);
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
this.storeListenDisposeLint = disposeList;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
getStyleDomById = (id: string) => {
|
|
366
|
-
const mediaStyleDomMap = this.mediaStyleDomMap;
|
|
367
|
-
let styleEl = mediaStyleDomMap[id];
|
|
368
|
-
if (!styleEl) {
|
|
369
|
-
styleEl = document.createElement('style');
|
|
370
|
-
styleEl.type = 'text/css';
|
|
371
|
-
mediaStyleDomMap[id] = styleEl;
|
|
372
|
-
}
|
|
373
|
-
styleEl.id = id;
|
|
374
|
-
return styleEl;
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
addMediaCSS = () => {
|
|
378
|
-
let header = this.domHeader;
|
|
379
|
-
if (!header) {
|
|
380
|
-
header = document.getElementsByTagName('head')?.[0];
|
|
381
|
-
this.domHeader = header;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (!this.domHeader) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const css = this._NODE_MODEL.value.css;
|
|
388
|
-
if (!css) {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
css.value.forEach((el) => {
|
|
392
|
-
const normalId = `${this.UNIQUE_ID}_${el.state}`;
|
|
393
|
-
let className = `.${css.class}`;
|
|
394
|
-
if (el.state !== 'normal') {
|
|
395
|
-
className = `${className}:${el.state}`;
|
|
396
|
-
}
|
|
397
|
-
if (Object.keys(el.style).length !== 0) {
|
|
398
|
-
const styleEl = this.getStyleDomById(normalId);
|
|
399
|
-
styleEl.innerText = `${className} { ${getCSSTextValue(el.style)} }`;
|
|
400
|
-
header?.appendChild(styleEl);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (el.media?.length) {
|
|
404
|
-
el.media.forEach((it) => {
|
|
405
|
-
const mediaId = `${normalId}_${it.type}_${it.value}`;
|
|
406
|
-
const styleDom = this.getStyleDomById(mediaId);
|
|
407
|
-
styleDom.media = `screen and (${it.type}:${it.value}px)`;
|
|
408
|
-
styleDom.innerHTML = `${className} { ${getCSSTextValue(it.style)} }`;
|
|
409
|
-
header?.appendChild(styleDom);
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
removeMediaCSS = () => {
|
|
416
|
-
const mediaStyleDomMap = this.mediaStyleDomMap;
|
|
417
|
-
Object.keys(mediaStyleDomMap).forEach((key) => {
|
|
418
|
-
this.domHeader?.removeChild(mediaStyleDomMap[key]);
|
|
419
|
-
});
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
componentDidMount(): void {
|
|
423
|
-
this.addMediaCSS();
|
|
424
|
-
if (that.onGetRef) {
|
|
425
|
-
that.onGetRef(this.targetComponentRef, nodeModel, this as any);
|
|
426
|
-
}
|
|
427
|
-
that.onComponentMount?.(this, nodeModel);
|
|
428
|
-
const forceUpdate = () => {
|
|
429
|
-
// stateName maybe changed
|
|
430
|
-
that.storeManager.setStore(nodeModel.value.stateName || nodeModel.id, this.storeState);
|
|
431
|
-
this.storeState.setState({
|
|
432
|
-
...this.state,
|
|
433
|
-
...(nodeModel.value.state || {}),
|
|
434
|
-
});
|
|
435
|
-
this.rebuildNode();
|
|
436
|
-
};
|
|
437
|
-
nodeModel.onChange(forceUpdate);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
rebuildNode = () => {
|
|
441
|
-
this.storeListenDisposeLint.forEach((el) => el());
|
|
442
|
-
this.removeMediaCSS();
|
|
443
|
-
this.connectStore();
|
|
444
|
-
this.addMediaCSS();
|
|
445
|
-
this.forceUpdate();
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
componentWillUnmount(): void {
|
|
449
|
-
this.storeListenDisposeLint.forEach((el) => el());
|
|
450
|
-
this.removeMediaCSS();
|
|
451
|
-
that.onComponentDestroy?.(this, nodeModel);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
render(): React.ReactNode {
|
|
455
|
-
const { $$context, ...props } = this.props;
|
|
456
|
-
const newOriginalProps = {
|
|
457
|
-
key: nodeModel.id,
|
|
458
|
-
...nodeModel.props,
|
|
459
|
-
...props,
|
|
460
|
-
};
|
|
461
|
-
const tempContext: ContextType = {
|
|
462
|
-
state: this.state || {},
|
|
463
|
-
updateState: this.updateState,
|
|
464
|
-
staticState: this.staticState,
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
if (nodeModel.value.componentName === InnerComponentNameEnum.ROOT_CONTAINER) {
|
|
468
|
-
tempContext.globalState = this.state;
|
|
469
|
-
tempContext.updateGlobalState = this.updateState;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
tempContext.stateManager = that.storeManager.getStateSnapshot();
|
|
473
|
-
const newContext = that.getContext(tempContext, $$context);
|
|
474
|
-
|
|
475
|
-
// 处理循环
|
|
476
|
-
const loopObj = nodeModel.value.loop;
|
|
477
|
-
let loopRes: any[] = [];
|
|
478
|
-
if (loopObj && loopObj.open) {
|
|
479
|
-
this.targetComponentRef.current = [];
|
|
480
|
-
let loopList: any[] = (loopObj.data as any[]) || [];
|
|
481
|
-
if (isExpression(loopObj.data)) {
|
|
482
|
-
const expProp = loopObj.data as JSExpressionPropType;
|
|
483
|
-
loopList = runExpression(expProp.value, newContext || {});
|
|
484
|
-
}
|
|
485
|
-
loopRes = loopList.map((...args) => {
|
|
486
|
-
const innerIndex = args[1];
|
|
487
|
-
const argsName = [loopObj.forName || 'item', loopObj.forIndex || 'index'];
|
|
488
|
-
const loopData = getObjFromArrayMap(args, argsName);
|
|
489
|
-
let loopDataName = 'loopData';
|
|
490
|
-
// loopDataName: loopData or loopData${xxx}, xxx is capitalize
|
|
491
|
-
if (loopObj.name) {
|
|
492
|
-
loopDataName = `${loopDataName}${loopObj.name}`;
|
|
493
|
-
}
|
|
494
|
-
const loopContext = that.getContext(
|
|
495
|
-
{
|
|
496
|
-
[loopDataName]: loopData,
|
|
497
|
-
staticState: this.staticState,
|
|
498
|
-
},
|
|
499
|
-
newContext
|
|
500
|
-
);
|
|
501
|
-
// handle props
|
|
502
|
-
const newProps: Record<string, any> = that.transformProps(newOriginalProps, {
|
|
503
|
-
$$context: loopContext,
|
|
504
|
-
});
|
|
505
|
-
// 处理 className
|
|
506
|
-
const classNames =
|
|
507
|
-
nodeModel.value.classNames?.map((it) => {
|
|
508
|
-
const name = it.name;
|
|
509
|
-
const status = isExpression(it.status) ? runExpression(String(it.status?.value || ''), loopContext) : false;
|
|
510
|
-
if (status) {
|
|
511
|
-
return name;
|
|
512
|
-
}
|
|
513
|
-
return '';
|
|
514
|
-
}) || [];
|
|
515
|
-
let finalClsx = `${newProps.className ?? ''} ${classNames.join(' ')}`.trim();
|
|
516
|
-
if (nodeModel.value.css) {
|
|
517
|
-
// 每个节点添加一个 表示节点唯一的 className, 使用 node.id
|
|
518
|
-
const className = `${nodeModel.value.css.class} ${finalClsx}`.trim();
|
|
519
|
-
finalClsx = className;
|
|
520
|
-
}
|
|
521
|
-
newProps.className = finalClsx;
|
|
522
|
-
|
|
523
|
-
// 处理 style
|
|
524
|
-
const newStyle: Record<string, any> = that.transformProps(nodeModel.value.style, {
|
|
525
|
-
$$context: loopContext,
|
|
526
|
-
});
|
|
527
|
-
// font-size to fontSize
|
|
528
|
-
if (nodeModel.value.style) {
|
|
529
|
-
newProps.style = formatSourceStylePropertyName(newStyle || {});
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
const { children } = newProps;
|
|
533
|
-
let newChildren: React.ReactNode[] = [];
|
|
534
|
-
if (children !== undefined) {
|
|
535
|
-
delete newProps.children;
|
|
536
|
-
newChildren = Array.isArray(children) ? children : [children];
|
|
537
|
-
} else {
|
|
538
|
-
const children: React.ReactNode[] = [];
|
|
539
|
-
const childModel = nodeModel.value.children;
|
|
540
|
-
childModel.forEach((node, index) => {
|
|
541
|
-
const child = that.buildComponent(node, {
|
|
542
|
-
$$context: loopContext,
|
|
543
|
-
idx: index,
|
|
544
|
-
});
|
|
545
|
-
children.push(child);
|
|
546
|
-
});
|
|
547
|
-
newChildren = children;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
newProps.key = `${newProps.key}-${innerIndex}`;
|
|
551
|
-
if (isExpression(loopObj.key)) {
|
|
552
|
-
const keyObj = loopObj.key as JSExpressionPropType;
|
|
553
|
-
const specialKey = runExpression(keyObj.value, loopContext || {});
|
|
554
|
-
newProps.key += `-${specialKey}`;
|
|
555
|
-
}
|
|
556
|
-
newProps.ref = (ref: any) => {
|
|
557
|
-
this.targetComponentRef.current = this.targetComponentRef.current || [];
|
|
558
|
-
this.targetComponentRef.current[innerIndex] = ref;
|
|
559
|
-
};
|
|
560
|
-
|
|
561
|
-
// handle children
|
|
562
|
-
return that.render(originalComponent, newProps, ...newChildren);
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
// 结束循环渲染
|
|
566
|
-
return loopRes;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
// handle props
|
|
570
|
-
const newProps: Record<string, any> = that.transformProps(newOriginalProps, {
|
|
571
|
-
$$context: newContext,
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
const { children } = newProps;
|
|
575
|
-
let newChildren: React.ReactNode[] = [];
|
|
576
|
-
if (children !== undefined) {
|
|
577
|
-
delete newProps.children;
|
|
578
|
-
newChildren = Array.isArray(children) ? children : [children];
|
|
579
|
-
} else {
|
|
580
|
-
const children: React.ReactNode[] = [];
|
|
581
|
-
const childModel = nodeModel.value.children;
|
|
582
|
-
childModel.forEach((node, index) => {
|
|
583
|
-
const child = that.buildComponent(node, {
|
|
584
|
-
$$context: newContext,
|
|
585
|
-
idx: index,
|
|
586
|
-
});
|
|
587
|
-
children.push(child);
|
|
588
|
-
});
|
|
589
|
-
newChildren = children;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
newProps.ref = this.targetComponentRef;
|
|
593
|
-
// 处理 className
|
|
594
|
-
const classNames =
|
|
595
|
-
nodeModel.value.classNames?.map((it) => {
|
|
596
|
-
const name = it.name;
|
|
597
|
-
const status = isExpression(it.status) ? runExpression(it.status?.value || '', newContext) : false;
|
|
598
|
-
if (status) {
|
|
599
|
-
return name;
|
|
600
|
-
}
|
|
601
|
-
return '';
|
|
602
|
-
}) || [];
|
|
603
|
-
|
|
604
|
-
let finalClsx = `${newProps.className ?? ''} ${classNames.join(' ')}`.trim();
|
|
605
|
-
if (nodeModel.value.css) {
|
|
606
|
-
// 每个节点添加一个 表示节点唯一的 className, 使用 node.id
|
|
607
|
-
const className = `${nodeModel.value.css.class} ${finalClsx}`.trim();
|
|
608
|
-
finalClsx = className;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
newProps.className = finalClsx;
|
|
612
|
-
|
|
613
|
-
// 处理 style
|
|
614
|
-
const newStyle: Record<string, any> = that.transformProps(nodeModel.value.style, {
|
|
615
|
-
$$context: newContext,
|
|
616
|
-
});
|
|
617
|
-
// font-size to fontSize
|
|
618
|
-
if (nodeModel.value.style) {
|
|
619
|
-
newProps.style = formatSourceStylePropertyName(newStyle || {});
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// handle children
|
|
623
|
-
let condition = nodeModel.value.condition ?? true;
|
|
624
|
-
if (typeof condition !== 'boolean') {
|
|
625
|
-
const conditionObj = condition as JSExpressionPropType;
|
|
626
|
-
condition = runExpression(conditionObj.value, newContext || {}) as boolean;
|
|
627
|
-
}
|
|
628
|
-
let finalNodeConfig = {
|
|
629
|
-
condition,
|
|
630
|
-
props: newProps,
|
|
631
|
-
};
|
|
632
|
-
if (that.processNodeConfigHook) {
|
|
633
|
-
finalNodeConfig = that.processNodeConfigHook(finalNodeConfig, nodeModel as CNode);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const renderView = that.render(originalComponent, finalNodeConfig.props, ...newChildren);
|
|
637
|
-
|
|
638
|
-
this._CONDITION = finalNodeConfig.condition as boolean;
|
|
639
|
-
if (!finalNodeConfig.condition) {
|
|
640
|
-
return React.createElement(
|
|
641
|
-
'div',
|
|
642
|
-
{
|
|
643
|
-
style: {
|
|
644
|
-
display: 'none',
|
|
645
|
-
},
|
|
646
|
-
},
|
|
647
|
-
renderView
|
|
648
|
-
);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
return renderView;
|
|
652
|
-
// 可能能复用 end
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
(DynamicComponent as any).displayName = `${nodeModel.value.componentName}Dynamic`;
|
|
657
|
-
|
|
658
|
-
return DynamicComponent;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// 递归建页面组件结构
|
|
662
|
-
buildComponent(
|
|
663
|
-
node: CNode | CRootNode | string,
|
|
664
|
-
{
|
|
665
|
-
$$context = {},
|
|
666
|
-
}: {
|
|
667
|
-
$$context: ContextType;
|
|
668
|
-
idx?: number;
|
|
669
|
-
}
|
|
670
|
-
) {
|
|
671
|
-
const runtimeComponentCache = this.runtimeComponentCache;
|
|
672
|
-
if (typeof node === 'string') {
|
|
673
|
-
return this.render(node);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
if (!isNodeModel(node)) {
|
|
677
|
-
return;
|
|
678
|
-
}
|
|
679
|
-
const handleNode = ({ currentNode }: { currentNode: CRootNode | CNode }) => {
|
|
680
|
-
const nodeId = currentNode.value.id;
|
|
681
|
-
let component = null;
|
|
682
|
-
if (runtimeComponentCache.get(nodeId)) {
|
|
683
|
-
component = runtimeComponentCache.get(nodeId);
|
|
684
|
-
} else {
|
|
685
|
-
const originalComponent = this.getComponent(currentNode);
|
|
686
|
-
|
|
687
|
-
component = this.convertModelToComponent(originalComponent, currentNode);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// cache runtime component
|
|
691
|
-
if (!runtimeComponentCache.get(nodeId) && this.renderMode !== 'design') {
|
|
692
|
-
runtimeComponentCache.set(nodeId, component);
|
|
693
|
-
}
|
|
694
|
-
const key = `${nodeId}-${DYNAMIC_COMPONENT_TYPE}`;
|
|
695
|
-
const props: Record<string, any> = {
|
|
696
|
-
$$context,
|
|
697
|
-
$$nodeModel: node,
|
|
698
|
-
key: key,
|
|
699
|
-
};
|
|
700
|
-
|
|
701
|
-
return this.render(component, props);
|
|
702
|
-
};
|
|
703
|
-
|
|
704
|
-
return handleNode({
|
|
705
|
-
currentNode: node,
|
|
706
|
-
});
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
// 真实渲染
|
|
710
|
-
render(
|
|
711
|
-
originalComponent: React.ComponentClass<any> | React.FunctionComponent | string,
|
|
712
|
-
props: Record<any, any> = {},
|
|
713
|
-
...children: React.ReactNode[]
|
|
714
|
-
) {
|
|
715
|
-
if (typeof originalComponent === 'string' || typeof originalComponent === 'number') {
|
|
716
|
-
return String(originalComponent);
|
|
717
|
-
}
|
|
718
|
-
InnerPropList.forEach((key) => {
|
|
719
|
-
if (key in props && (originalComponent as any).__CP_TYPE__ !== DYNAMIC_COMPONENT_TYPE) {
|
|
720
|
-
delete props[key];
|
|
721
|
-
}
|
|
722
|
-
});
|
|
723
|
-
const res = React.createElement(originalComponent, props, ...children);
|
|
724
|
-
return res;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
clear() {
|
|
728
|
-
this.runtimeComponentCache.clear();
|
|
729
|
-
this.storeManager.destroy();
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
734
|
-
export const ReactAdapter = getAdapter(new DefineReactAdapter());
|