@cqsjjb/jjb-cloud-component 0.0.1

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.
@@ -0,0 +1,42 @@
1
+ // @ts-ignore
2
+ import * as React from 'react';
3
+
4
+ interface ComponentProps {
5
+ ref?: React.Ref<{ [ p: string ]: any }>;
6
+ children?: React.ReactNode;
7
+ }
8
+
9
+ interface CloudComponentProps extends ComponentProps {
10
+ // 组件资源地址
11
+ from: string;
12
+ // 是否需要初始化更新settings和dataSource
13
+ initialize?: boolean;
14
+ // 组件唯一key
15
+ componentKey: string;
16
+ // 组件的额外Props
17
+ componentProps?: {};
18
+ // 组件开始加载
19
+ onLoadStart?: () => void;
20
+ // 组件结束加载
21
+ onLoadEnd?: () => void;
22
+ // 组件销毁
23
+ onDestroy?: () => void;
24
+ // 组件已挂载
25
+ onMounted?: (key: string, ref: {
26
+ // 组件输出的表单配置
27
+ formItems?: {},
28
+ // 组件更新
29
+ updateData?: (settings?: {}, dataSource?: any) => void;
30
+ }) => void;
31
+ // 组件已更新
32
+ onUpdated?: (key: string, ref: {
33
+ settings?: {},
34
+ dataSource?: any
35
+ }) => void;
36
+ }
37
+
38
+ interface CloudComponentFc extends React.FC<CloudComponentProps> {
39
+ }
40
+
41
+ declare const CloudComponent: CloudComponentFc;
42
+ export default CloudComponent;
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+
3
+ import { tools } from '@cqsjjb/jjb-common-lib';
4
+
5
+ import ImportCloudComponent from './import-cloud-component';
6
+
7
+ function unMountCloudComponentStyle(styleId) {
8
+ const root = document.querySelector('head');
9
+ const styled = root.querySelectorAll(`[data-cloud-component-style-id="${styleId}"]`);
10
+ for (const style of styled) {
11
+ root.removeChild(style);
12
+ }
13
+ }
14
+
15
+ export default function CloudComponent(props) {
16
+ let styleId;
17
+ const [ Component, setComponent ] = React.useState(null);
18
+ const {
19
+ from,
20
+ initialize,
21
+ componentKey,
22
+ componentProps,
23
+ onLoadStart,
24
+ onLoadEnd,
25
+ onDestroy,
26
+ onMounted,
27
+ onUpdated
28
+ } = props;
29
+
30
+ React.useEffect(() => {
31
+ async function load() {
32
+ onLoadStart && onLoadStart();
33
+ const {
34
+ module,
35
+ styleId: _styleId
36
+ } = await ImportCloudComponent({ from });
37
+
38
+ styleId = _styleId;
39
+
40
+ setComponent(() => {
41
+ onLoadEnd && onLoadEnd();
42
+ return module.default();
43
+ });
44
+ }
45
+
46
+ load().then(() => null);
47
+
48
+ return () => {
49
+ unMountCloudComponentStyle(styleId);
50
+ onDestroy && onDestroy();
51
+ };
52
+ }, []);
53
+
54
+ return Component && (
55
+ <Component
56
+ initialize={initialize}
57
+ {...{
58
+ detail: { componentKey },
59
+ ...tools.toObject(componentProps)
60
+ }}
61
+ onMounted={onMounted}
62
+ onUpdated={onUpdated}
63
+ />
64
+ );
65
+ }
@@ -0,0 +1,32 @@
1
+ // @ts-ignore
2
+ import React from 'react';
3
+
4
+ declare function ImportCloudComponent (options: {
5
+ // 组件依赖库变量
6
+ lib?: string;
7
+ // 组件地址
8
+ from: string;
9
+ }): {
10
+ styleId: string;
11
+ module: {
12
+ // 组件信息
13
+ info: {
14
+ // 组件名称
15
+ name: string;
16
+ // 组件说明
17
+ remark: string;
18
+ // 组件版本
19
+ version: string;
20
+ // 组件描述
21
+ description: string;
22
+ // 组件环境
23
+ environment: {};
24
+ // 组件依赖
25
+ dependencies?: { [ p: string ]: string }
26
+ },
27
+ // 组件本体
28
+ default: () => React.Component
29
+ }
30
+ }
31
+
32
+ export default ImportCloudComponent;
@@ -0,0 +1,143 @@
1
+ import { tools } from '@cqsjjb/jjb-common-lib';
2
+
3
+ /**
4
+ * @description 优化依赖变量
5
+ * @param name {string} 依赖变量名
6
+ * @return {*|string}
7
+ */
8
+ function ansLibField(name) {
9
+ return name.indexOf('.') !== -1
10
+ ? name
11
+ : `.${name}`;
12
+ }
13
+
14
+ /**
15
+ * @description 给地址加随机字符串
16
+ * @param url {string} 地址
17
+ * @return {string}
18
+ */
19
+ function fromURL(url) {
20
+ return `${url}${url.indexOf('?') !== -1
21
+ ? '&'
22
+ : '?'}v=${new Date().getTime()}`;
23
+ }
24
+
25
+ /**
26
+ * @description 生成CJS运行环境
27
+ * @param {string} lib 云组件依赖变量
28
+ * @param {string} from 云组件地址
29
+ * @param {string} code 注入云组件代码
30
+ */
31
+ function genCommonJSRuntime({
32
+ lib,
33
+ from
34
+ }, code) {
35
+ const styleId = tools.createOnlyKey();
36
+ return {
37
+ styleId,
38
+ useModule: new Function(`
39
+ /* cloud-component-assets: ${from} */
40
+ const module = { exports: null };
41
+ const exports = {};
42
+ const require = function (id) {
43
+ return window${ansLibField(lib)}[ id ];
44
+ };
45
+ /* cloud-component-code */
46
+ ${code.replace(/\{cloudComponentStyleId\}/g, styleId)}
47
+ /* cloud-component-code */
48
+ return Object.assign(module.exports, exports);
49
+ `)
50
+ };
51
+ }
52
+
53
+ function print(msg) {
54
+ return `[ImportCloudComponent]: ${msg}`;
55
+ }
56
+
57
+ /**
58
+ * @description 宿主环境依赖检测
59
+ * @param lib {string} 依赖变量
60
+ * @param name {string} 依赖名称
61
+ * @return {boolean}
62
+ */
63
+ function checkDependence(lib, name) {
64
+ return tools.isUndefined(window[ lib ][ name ]);
65
+ }
66
+
67
+ /**
68
+ * @description 依赖检测
69
+ * @param lib {string}
70
+ * @param dependencies {string[]}
71
+ * @param isProxy {boolean}
72
+ * @return {Array<{ name: string, check: boolean }>}
73
+ */
74
+ function checkDependencies(lib, dependencies, isProxy) {
75
+ return Object.keys(dependencies).map(name => {
76
+ return {
77
+ name,
78
+ check: checkDependence(lib, name, isProxy)
79
+ };
80
+ }).filter(i => i.check);
81
+ }
82
+
83
+ /**
84
+ * @description 手动加载模块
85
+ * @param options {{ from: string, lib: string }}
86
+ * @example
87
+ * Import({
88
+ * from: 'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js'
89
+ * }).then(res => {
90
+ * console.log(res);
91
+ * });
92
+ * @return {Promise<{ module: { info: {}, default:() => React.Component }, styleId: string }>}
93
+ */
94
+ export default function ImportCloudComponent(options) {
95
+ const lib = options.lib || '__coreLib';
96
+ const from = options.from;
97
+
98
+ if (!from) {
99
+ throw Error(print('云组件资源访问地址不能为空!'));
100
+ }
101
+
102
+ return fetch(fromURL(from))
103
+ .then(response => response.text())
104
+ .then(response => {
105
+ const {
106
+ styleId,
107
+ useModule
108
+ } = genCommonJSRuntime({
109
+ lib,
110
+ from
111
+ }, response);
112
+ // 获取云组件导出CJS模块
113
+ const module = useModule();
114
+ // 获取云组件info变量
115
+ const { info } = module;
116
+ // 判断当前云组件是否导出了info变量
117
+ if (tools.isUndefined(info)) {
118
+ throw Error(print(`${from} 缺少info变量导出, 无法获知此组件的基本信息, 请在组件包入口处导出组件的info变量!`));
119
+ }
120
+ // 获取云组件的基本信息
121
+ const {
122
+ name,
123
+ dependencies
124
+ } = info;
125
+ // 判断云组件是否有依赖配置
126
+ if (!tools.isEmptyObject(dependencies)) {
127
+ // 是否存在未安装的依赖项
128
+ const noInstallDependencies = checkDependencies(lib, dependencies);
129
+ // 判断是否有
130
+ if (tools.isValidArray(noInstallDependencies)) {
131
+ throw Error(print(`${name} 需要${noInstallDependencies.at(0).name}依赖, 请在window.${lib}中提供此依赖!`));
132
+ }
133
+ }
134
+
135
+ console.log(print(`${module.info.name} 加载完成!`));
136
+
137
+ // 返回组件CSJ模块
138
+ return {
139
+ module,
140
+ styleId
141
+ };
142
+ });
143
+ }
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ import CloudComponent from './cloud-component';
2
+ import ImportCloudComponent from './import-cloud-component';
3
+
4
+ export {
5
+ CloudComponent,
6
+ ImportCloudComponent
7
+ };
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@cqsjjb/jjb-cloud-component",
3
+ "version": "0.0.1",
4
+ "description": "前端-云组件",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ },
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "typings": "index.d.ts",
12
+ "author": "jiaoxiwei",
13
+ "license": "MIT",
14
+ "dependencies": {
15
+
16
+ }
17
+ }