|
1 |
| -import { CreateContainerOptions, createContainer } from '../container'; |
2 |
| -import { createCodeRuntime, createScope } from '../code-runtime'; |
3 |
| -import { throwRuntimeError } from '../utils/error'; |
4 |
| -import { validateContainerSchema } from '../validator/schema'; |
5 |
| - |
6 |
| -export interface ComponentOptionsBase<C> { |
7 |
| - componentsTree: RootSchema; |
8 |
| - componentsRecord: Record<string, C | Package>; |
9 |
| - dataSourceCreator: DataSourceCreator; |
10 |
| -} |
11 |
| - |
12 |
| -export function createComponentFunction<C, O extends ComponentOptionsBase<C>>(options: { |
13 |
| - stateCreator: (initState: AnyObject) => StateContext; |
14 |
| - componentCreator: (container: Container, componentOptions: O) => C; |
15 |
| - defaultOptions?: Partial<O>; |
16 |
| -}): (componentOptions: O) => C { |
17 |
| - const { stateCreator, componentCreator, defaultOptions = {} } = options; |
18 |
| - |
| 1 | +import { type CreateContainerOptions, createContainer, type Container } from '../container'; |
| 2 | +import type { PlainObject, InstanceStateApi } from '../types'; |
| 3 | + |
| 4 | +export type CreateComponentBaseOptions<T extends string> = Omit< |
| 5 | + CreateContainerOptions<T>, |
| 6 | + 'stateCreator' |
| 7 | +>; |
| 8 | + |
| 9 | +/** |
| 10 | + * 创建 createComponent 的辅助函数 |
| 11 | + * createComponent = createComponentFunction(() => component) |
| 12 | + */ |
| 13 | +export function createComponentFunction< |
| 14 | + ComponentT, |
| 15 | + InstanceT, |
| 16 | + LifeCycleNameT extends string, |
| 17 | + O extends CreateComponentBaseOptions<LifeCycleNameT>, |
| 18 | +>( |
| 19 | + stateCreator: (initState: PlainObject) => InstanceStateApi, |
| 20 | + componentCreator: ( |
| 21 | + container: Container<InstanceT, LifeCycleNameT>, |
| 22 | + componentOptions: O, |
| 23 | + ) => ComponentT, |
| 24 | +): (componentOptions: O) => ComponentT { |
19 | 25 | return (componentOptions) => {
|
20 |
| - const finalOptions = Object.assign({}, defaultOptions, componentOptions); |
21 |
| - const { supCodeScope, initScopeValue = {}, dataSourceCreator } = finalOptions; |
22 |
| - |
23 |
| - const codeRuntimeScope = |
24 |
| - supCodeScope?.createSubScope(initScopeValue) ?? createScope(initScopeValue); |
25 |
| - const codeRuntime = createCodeRuntime(codeRuntimeScope); |
26 |
| - |
27 |
| - const container: Container = { |
28 |
| - get codeScope() { |
29 |
| - return codeRuntimeScope; |
30 |
| - }, |
31 |
| - get codeRuntime() { |
32 |
| - return codeRuntime; |
33 |
| - }, |
34 |
| - |
35 |
| - createInstance(componentsTree, extraProps = {}) { |
36 |
| - if (!validateContainerSchema(componentsTree)) { |
37 |
| - throwRuntimeError('createComponent', 'componentsTree is not valid!'); |
38 |
| - } |
39 |
| - |
40 |
| - const mapRefToComponentInstance: Map<string, C> = new Map(); |
41 |
| - |
42 |
| - const initialState = codeRuntime.parseExprOrFn(componentsTree.state ?? {}); |
43 |
| - const stateContext = stateCreator(initialState); |
44 |
| - |
45 |
| - codeRuntimeScope.setValue( |
46 |
| - Object.assign( |
47 |
| - { |
48 |
| - props: codeRuntime.parseExprOrFn({ |
49 |
| - ...componentsTree.defaultProps, |
50 |
| - ...componentsTree.props, |
51 |
| - ...extraProps, |
52 |
| - }), |
53 |
| - $(ref: string) { |
54 |
| - return mapRefToComponentInstance.get(ref); |
55 |
| - }, |
56 |
| - }, |
57 |
| - stateContext, |
58 |
| - dataSourceCreator |
59 |
| - ? dataSourceCreator(componentsTree.dataSource ?? ({ list: [] } as any), stateContext) |
60 |
| - : {}, |
61 |
| - ) as ContainerInstanceScope<C>, |
62 |
| - true, |
63 |
| - ); |
64 |
| - |
65 |
| - if (componentsTree.methods) { |
66 |
| - for (const [key, fn] of Object.entries(componentsTree.methods)) { |
67 |
| - const customMethod = codeRuntime.createFnBoundScope(fn.value); |
68 |
| - if (customMethod) { |
69 |
| - codeRuntimeScope.inject(key, customMethod); |
70 |
| - } |
71 |
| - } |
72 |
| - } |
73 |
| - |
74 |
| - triggerLifeCycle('constructor'); |
75 |
| - |
76 |
| - function triggerLifeCycle(lifeCycleName: LifeCycleNameT, ...args: any[]) { |
77 |
| - // keys 用来判断 lifeCycleName 存在于 schema 对象上,不获取原型链上的对象 |
78 |
| - if ( |
79 |
| - !componentsTree.lifeCycles || |
80 |
| - !Object.keys(componentsTree.lifeCycles).includes(lifeCycleName) |
81 |
| - ) { |
82 |
| - return; |
83 |
| - } |
84 |
| - |
85 |
| - const lifeCycleSchema = componentsTree.lifeCycles[lifeCycleName]; |
86 |
| - if (isJsFunction(lifeCycleSchema)) { |
87 |
| - const lifeCycleFn = codeRuntime.createFnBoundScope(lifeCycleSchema.value); |
88 |
| - if (lifeCycleFn) { |
89 |
| - lifeCycleFn.apply(codeRuntime.getScope().value, args); |
90 |
| - } |
91 |
| - } |
92 |
| - } |
93 |
| - |
94 |
| - const instance: ContainerInstance<C> = { |
95 |
| - get id() { |
96 |
| - return componentsTree.id; |
97 |
| - }, |
98 |
| - get cssText() { |
99 |
| - return componentsTree.css; |
100 |
| - }, |
101 |
| - get codeScope() { |
102 |
| - return codeRuntimeScope; |
103 |
| - }, |
104 |
| - |
105 |
| - triggerLifeCycle, |
106 |
| - setRefInstance(ref, instance) { |
107 |
| - mapRefToComponentInstance.set(ref, instance); |
108 |
| - }, |
109 |
| - removeRefInstance(ref) { |
110 |
| - mapRefToComponentInstance.delete(ref); |
111 |
| - }, |
112 |
| - getComponentTreeNodes() { |
113 |
| - const childNodes = componentsTree.children |
114 |
| - ? Array.isArray(componentsTree.children) |
115 |
| - ? componentsTree.children |
116 |
| - : [componentsTree.children] |
117 |
| - : []; |
118 |
| - const treeNodes = childNodes.map((item) => { |
119 |
| - return createComponentTreeNode(item, undefined); |
120 |
| - }); |
121 |
| - |
122 |
| - return treeNodes; |
123 |
| - }, |
124 |
| - |
125 |
| - destory() { |
126 |
| - mapRefToComponentInstance.clear(); |
127 |
| - codeRuntimeScope.setValue({}); |
128 |
| - }, |
129 |
| - }; |
130 |
| - |
131 |
| - return instance; |
132 |
| - }, |
133 |
| - }; |
| 26 | + const { |
| 27 | + supCodeScope, |
| 28 | + initScopeValue = {}, |
| 29 | + dataSourceCreator, |
| 30 | + componentsTree, |
| 31 | + } = componentOptions; |
| 32 | + |
| 33 | + const container = createContainer<InstanceT, LifeCycleNameT>({ |
| 34 | + supCodeScope, |
| 35 | + initScopeValue, |
| 36 | + stateCreator, |
| 37 | + dataSourceCreator, |
| 38 | + componentsTree, |
| 39 | + }); |
134 | 40 |
|
135 | 41 | return componentCreator(container, componentOptions);
|
136 | 42 | };
|
|
0 commit comments