@cqsjjb/jjb-cloud-component 0.0.7-experimental.2 → 0.0.7
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/cloud-component.d.ts +16 -2
- package/cloud-component.js +92 -13
- package/import-cloud-component.js +3 -3
- package/package.json +1 -1
package/cloud-component.d.ts
CHANGED
|
@@ -11,9 +11,21 @@ interface ComponentProps {
|
|
|
11
11
|
*/
|
|
12
12
|
export function useUnMountCloudComponentStyle (styleId: string): void;
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @description 云组件默认内置依赖项
|
|
16
|
+
* 所有云组件都可以直接使用这些依赖,无需手动传递
|
|
17
|
+
*/
|
|
18
|
+
interface DefaultDependencies {
|
|
19
|
+
'react': any;
|
|
20
|
+
'react-dom': any;
|
|
21
|
+
'@cqsjjb/jjb-common-lib': any;
|
|
22
|
+
}
|
|
23
|
+
|
|
14
24
|
interface CloudComponentProps extends ComponentProps {
|
|
15
|
-
//
|
|
16
|
-
|
|
25
|
+
// 组件依赖,支持函数引用(如require()的结果)
|
|
26
|
+
// 默认内置依赖:react, react-dom, @cqsjjb/jjb-common-lib
|
|
27
|
+
// 用户自定义依赖会与默认依赖合并,同名依赖会被覆盖
|
|
28
|
+
dependencies?: { [ p: string ]: any }
|
|
17
29
|
// 组件资源地址
|
|
18
30
|
from: string;
|
|
19
31
|
// 缓存
|
|
@@ -26,6 +38,8 @@ interface CloudComponentProps extends ComponentProps {
|
|
|
26
38
|
componentKey: string;
|
|
27
39
|
// 组件的额外Props
|
|
28
40
|
componentProps?: Record<string, unknown>;
|
|
41
|
+
// 组件引用
|
|
42
|
+
componentRef?: React.Ref<Record<string, unknown>>;
|
|
29
43
|
// 组件开始加载
|
|
30
44
|
onLoadStart?: () => void;
|
|
31
45
|
// 组件结束加载
|
package/cloud-component.js
CHANGED
|
@@ -19,6 +19,9 @@ export function useUnMountCloudComponentStyle(styleId) {
|
|
|
19
19
|
/**
|
|
20
20
|
* @description 云组件
|
|
21
21
|
* @param props {object} 组件props
|
|
22
|
+
* @param props.dependencies {object} 自定义依赖项,会与默认依赖项合并
|
|
23
|
+
* @note 默认内置依赖项:react, react-dom, @cqsjjb/jjb-common-lib
|
|
24
|
+
* @note 用户自定义依赖项会覆盖同名的默认依赖项
|
|
22
25
|
*/
|
|
23
26
|
export default function CloudComponent(props) {
|
|
24
27
|
let styleId;
|
|
@@ -27,7 +30,7 @@ export default function CloudComponent(props) {
|
|
|
27
30
|
from,
|
|
28
31
|
cache,
|
|
29
32
|
headers,
|
|
30
|
-
dependencies =
|
|
33
|
+
dependencies = {},
|
|
31
34
|
initialize,
|
|
32
35
|
componentRef,
|
|
33
36
|
componentKey,
|
|
@@ -39,10 +42,73 @@ export default function CloudComponent(props) {
|
|
|
39
42
|
onUpdated
|
|
40
43
|
} = props;
|
|
41
44
|
|
|
45
|
+
// 默认内置依赖项,所有云组件都可以使用
|
|
46
|
+
const defaultDependencies = {
|
|
47
|
+
'react': require('react'),
|
|
48
|
+
'react-dom': require('react-dom'),
|
|
49
|
+
'@cqsjjb/jjb-common-lib': require('@cqsjjb/jjb-common-lib')
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// 合并默认依赖和用户自定义依赖,用户依赖优先级更高
|
|
53
|
+
const mergedDependencies = React.useMemo(() => {
|
|
54
|
+
return {
|
|
55
|
+
...defaultDependencies,
|
|
56
|
+
...dependencies
|
|
57
|
+
};
|
|
58
|
+
}, [dependencies]);
|
|
59
|
+
|
|
60
|
+
// 使用 useMemo 来稳定化 mergedDependencies 引用,避免不必要的重新渲染
|
|
61
|
+
const stableDependencies = React.useMemo(() => {
|
|
62
|
+
return mergedDependencies;
|
|
63
|
+
}, [mergedDependencies]);
|
|
64
|
+
|
|
65
|
+
// 使用 useRef 来跟踪 dependencies 的变化,避免因对象引用变化导致的重新渲染
|
|
66
|
+
const prevDependenciesRef = React.useRef();
|
|
67
|
+
const shouldReloadDependencies = React.useMemo(() => {
|
|
68
|
+
if (!prevDependenciesRef.current) {
|
|
69
|
+
prevDependenciesRef.current = mergedDependencies;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 比较 dependencies 的键和值
|
|
74
|
+
const prevKeys = Object.keys(prevDependenciesRef.current);
|
|
75
|
+
const currentKeys = Object.keys(mergedDependencies);
|
|
76
|
+
|
|
77
|
+
if (prevKeys.length !== currentKeys.length) {
|
|
78
|
+
prevDependenciesRef.current = mergedDependencies;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
for (const key of currentKeys) {
|
|
83
|
+
if (prevDependenciesRef.current[key] !== mergedDependencies[key]) {
|
|
84
|
+
prevDependenciesRef.current = mergedDependencies;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return false;
|
|
90
|
+
}, [mergedDependencies]);
|
|
91
|
+
|
|
92
|
+
// 使用 useRef 来存储回调函数,避免因回调函数重新创建导致的重新渲染
|
|
93
|
+
const onLoadStartRef = React.useRef(onLoadStart);
|
|
94
|
+
const onLoadEndRef = React.useRef(onLoadEnd);
|
|
95
|
+
const onDestroyRef = React.useRef(onDestroy);
|
|
96
|
+
|
|
42
97
|
React.useEffect(() => {
|
|
98
|
+
onLoadStartRef.current = onLoadStart;
|
|
99
|
+
onLoadEndRef.current = onLoadEnd;
|
|
100
|
+
onDestroyRef.current = onDestroy;
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
React.useEffect(() => {
|
|
104
|
+
// 只有当 dependencies 真正发生变化时才重新加载
|
|
105
|
+
if (!shouldReloadDependencies && prevDependenciesRef.current) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
43
109
|
async function load() {
|
|
44
110
|
try {
|
|
45
|
-
|
|
111
|
+
onLoadStartRef.current && onLoadStartRef.current();
|
|
46
112
|
const {
|
|
47
113
|
module,
|
|
48
114
|
styleId: _styleId,
|
|
@@ -51,20 +117,25 @@ export default function CloudComponent(props) {
|
|
|
51
117
|
from,
|
|
52
118
|
cache,
|
|
53
119
|
headers,
|
|
54
|
-
dependencies
|
|
120
|
+
dependencies: stableDependencies
|
|
55
121
|
});
|
|
56
122
|
|
|
57
123
|
styleId = _styleId;
|
|
58
124
|
|
|
59
125
|
setComponent(() => {
|
|
60
|
-
|
|
126
|
+
onLoadEndRef.current && onLoadEndRef.current();
|
|
61
127
|
return isNewVersion
|
|
62
|
-
? module.default(
|
|
128
|
+
? module.default({
|
|
129
|
+
// 组件引用
|
|
130
|
+
ref: componentRef,
|
|
131
|
+
// 将依赖项穿透下去,用于在组件内部使用依赖项(支持云组件嵌套云组件)
|
|
132
|
+
$$dependencies: stableDependencies
|
|
133
|
+
})
|
|
63
134
|
: module.default;
|
|
64
135
|
});
|
|
65
136
|
} catch (error) {
|
|
66
137
|
console.error('云组件加载失败:', error);
|
|
67
|
-
|
|
138
|
+
onLoadEndRef.current && onLoadEndRef.current();
|
|
68
139
|
// 可以设置一个错误组件或显示错误信息
|
|
69
140
|
setComponent(() => () => React.createElement('div', {
|
|
70
141
|
style: { color: 'red', padding: '10px' }
|
|
@@ -78,17 +149,25 @@ export default function CloudComponent(props) {
|
|
|
78
149
|
if (styleId) {
|
|
79
150
|
useUnMountCloudComponentStyle(styleId);
|
|
80
151
|
}
|
|
81
|
-
|
|
152
|
+
onDestroyRef.current && onDestroyRef.current();
|
|
82
153
|
};
|
|
83
|
-
}, [from, cache, headers,
|
|
154
|
+
}, [from, cache, headers, shouldReloadDependencies]);
|
|
155
|
+
|
|
156
|
+
// 使用 useMemo 来稳定化 componentProps,避免因对象重新创建导致的重新渲染
|
|
157
|
+
const stableComponentProps = React.useMemo(() => {
|
|
158
|
+
return {
|
|
159
|
+
detail: { componentKey },
|
|
160
|
+
...tools.toObject(componentProps)
|
|
161
|
+
};
|
|
162
|
+
}, [componentKey, JSON.stringify(componentProps)]);
|
|
163
|
+
|
|
164
|
+
// 使用 useMemo 来稳定化 initialize 函数
|
|
165
|
+
const stableInitialize = React.useMemo(() => initialize, [initialize]);
|
|
84
166
|
|
|
85
167
|
return Component && (
|
|
86
168
|
<Component
|
|
87
|
-
initialize={
|
|
88
|
-
{...
|
|
89
|
-
detail: { componentKey },
|
|
90
|
-
...tools.toObject(componentProps)
|
|
91
|
-
}}
|
|
169
|
+
initialize={stableInitialize}
|
|
170
|
+
{...stableComponentProps}
|
|
92
171
|
onMounted={onMounted}
|
|
93
172
|
onUpdated={onUpdated}
|
|
94
173
|
/>
|
|
@@ -70,10 +70,10 @@ export default async function ImportCloudComponent(options) {
|
|
|
70
70
|
} catch (error) {
|
|
71
71
|
throw new Error(`云组件加载失败: ${error.message}`);
|
|
72
72
|
}
|
|
73
|
-
const
|
|
73
|
+
const __dependencies = {};
|
|
74
74
|
|
|
75
75
|
Object.entries(dependencies).forEach(([key, value]) => {
|
|
76
|
-
|
|
76
|
+
__dependencies[key] = value;
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
let module;
|
|
@@ -89,7 +89,7 @@ export default async function ImportCloudComponent(options) {
|
|
|
89
89
|
useModule = runtime.useModule;
|
|
90
90
|
|
|
91
91
|
// 获取云组件导出CJS模块
|
|
92
|
-
module = useModule(
|
|
92
|
+
module = useModule(__dependencies);
|
|
93
93
|
|
|
94
94
|
if (!module || typeof module !== 'object') {
|
|
95
95
|
throw new Error('云组件模块格式错误');
|