@hhfenpm/micro-app 1.0.6 → 1.0.8
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/README.md +40 -25
- package/dist/index.esm.js +170 -101
- package/dist/index.js +170 -103
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,12 +14,12 @@ yarn add @hhfenpm/micro-app
|
|
|
14
14
|
|
|
15
15
|
## 能力概览
|
|
16
16
|
|
|
17
|
-
| 能力
|
|
18
|
-
|
|
19
|
-
| **通信桥接** | 子应用通过 `vm.$base.命名空间.方法(params)` 调用父应用方法,支持 Promise
|
|
20
|
-
| **状态同步** | 父子应用 Vuex `base` 模块双向同步
|
|
17
|
+
| 能力 | 说明 |
|
|
18
|
+
| ------------ | ----------------------------------------------------------------------------------- |
|
|
19
|
+
| **通信桥接** | 子应用通过 `vm.$base.命名空间.方法(params)` 调用父应用方法,支持 Promise |
|
|
20
|
+
| **状态同步** | 父子应用 Vuex `base` 模块双向同步 |
|
|
21
21
|
| **生命周期** | 父应用调用 `mount/update/unmount`,子应用通过 `window.__MICRO_APP_LIFECYCLE__` 响应 |
|
|
22
|
-
| **路由同步** | 子应用路由变化同步到父应用 URL(需子应用调用 `store.attachRouterSync(router)`)
|
|
22
|
+
| **路由同步** | 子应用路由变化同步到父应用 URL(需子应用调用 `store.attachRouterSync(router)`) |
|
|
23
23
|
|
|
24
24
|
---
|
|
25
25
|
|
|
@@ -32,14 +32,16 @@ yarn add @hhfenpm/micro-app
|
|
|
32
32
|
```javascript
|
|
33
33
|
import { initBridge, createRegisterHandlers } from '@hhfenpm/micro-app'
|
|
34
34
|
|
|
35
|
-
const vm = new Vue({
|
|
35
|
+
const vm = new Vue({
|
|
36
|
+
/* ... */
|
|
37
|
+
})
|
|
36
38
|
|
|
37
39
|
// getElectron:返回 electron 模块,无则 () => ({}) 或 () => require('@/utils/electron')
|
|
38
40
|
const getElectron = () => ({}) // 或 () => require('@/utils/electron')
|
|
39
41
|
const toHandlers = createRegisterHandlers(getElectron)
|
|
40
42
|
|
|
41
43
|
initBridge({
|
|
42
|
-
|
|
44
|
+
isBase: true,
|
|
43
45
|
vm,
|
|
44
46
|
handlers: toHandlers(vm),
|
|
45
47
|
iframeSelector: '#microApp', // 可选,默认 '#microApp'
|
|
@@ -56,13 +58,17 @@ initBridge({
|
|
|
56
58
|
```javascript
|
|
57
59
|
import { initBridge } from '@hhfenpm/micro-app'
|
|
58
60
|
|
|
59
|
-
const vm = new Vue({
|
|
61
|
+
const vm = new Vue({
|
|
62
|
+
/* ... */
|
|
63
|
+
})
|
|
60
64
|
|
|
61
|
-
initBridge({
|
|
65
|
+
initBridge({ isBase: false, vm })
|
|
62
66
|
|
|
63
67
|
// 调用父应用:vm.$base.命名空间.方法(params),返回 Promise
|
|
64
68
|
vm.$base.ui.$message('来自子应用')
|
|
65
|
-
vm.$base.ui.$confirm('确认?').then(ok => {
|
|
69
|
+
vm.$base.ui.$confirm('确认?').then(ok => {
|
|
70
|
+
/* ... */
|
|
71
|
+
})
|
|
66
72
|
vm.$base.cs.show()
|
|
67
73
|
```
|
|
68
74
|
|
|
@@ -77,7 +83,7 @@ import { createMicroAppCore } from '@hhfenpm/micro-app'
|
|
|
77
83
|
|
|
78
84
|
const modelMap = () => ({
|
|
79
85
|
'disease-analysis': ['/disease-analysis', '/ds-consult'],
|
|
80
|
-
|
|
86
|
+
health: ['/health-manage'],
|
|
81
87
|
})
|
|
82
88
|
|
|
83
89
|
const core = createMicroAppCore({
|
|
@@ -86,7 +92,7 @@ const core = createMicroAppCore({
|
|
|
86
92
|
})
|
|
87
93
|
|
|
88
94
|
// 根据路径得到模块名,未命中或未启用则为 null
|
|
89
|
-
const module = core.microAppModule('/disease-analysis')
|
|
95
|
+
const module = core.microAppModule('/disease-analysis') // 'disease-analysis'
|
|
90
96
|
|
|
91
97
|
// 子应用完整 URL(含 hash)
|
|
92
98
|
const src = core.microAppSrc('/disease-analysis')
|
|
@@ -110,7 +116,7 @@ import base from './store/modules/base' // 需含 base/SYNC_STATE
|
|
|
110
116
|
|
|
111
117
|
const store = new Vuex.Store({
|
|
112
118
|
modules: { base },
|
|
113
|
-
plugins: [baseSyncPlugin({
|
|
119
|
+
plugins: [baseSyncPlugin({ isBase: true, iframeSelector: '#microApp' })],
|
|
114
120
|
})
|
|
115
121
|
```
|
|
116
122
|
|
|
@@ -122,7 +128,7 @@ import base from './store/modules/base'
|
|
|
122
128
|
|
|
123
129
|
const store = new Vuex.Store({
|
|
124
130
|
modules: { base },
|
|
125
|
-
plugins: [baseSyncPlugin({
|
|
131
|
+
plugins: [baseSyncPlugin({ isBase: false, iframeSelector: '#microApp' })],
|
|
126
132
|
})
|
|
127
133
|
|
|
128
134
|
import router from './router'
|
|
@@ -141,9 +147,15 @@ store.attachRouterSync(router) // 必调,用于把子应用路由同步到父
|
|
|
141
147
|
|
|
142
148
|
```javascript
|
|
143
149
|
window.__MICRO_APP_LIFECYCLE__ = {
|
|
144
|
-
mount(payload) {
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
mount(payload) {
|
|
151
|
+
/* 挂载后 */
|
|
152
|
+
},
|
|
153
|
+
update(payload) {
|
|
154
|
+
/* 更新时,如路由变化 */
|
|
155
|
+
},
|
|
156
|
+
unmount(payload) {
|
|
157
|
+
/* 卸载前 */
|
|
158
|
+
},
|
|
147
159
|
}
|
|
148
160
|
```
|
|
149
161
|
|
|
@@ -161,30 +173,33 @@ store.callMicroAppLifeCycle('unmount')
|
|
|
161
173
|
|
|
162
174
|
## API 一览
|
|
163
175
|
|
|
164
|
-
| 接口
|
|
165
|
-
|
|
166
|
-
| `initBridge({
|
|
167
|
-
| `createRegisterHandlers(getElectron?)`
|
|
168
|
-
| `createMicroAppCore({ modelMap, enabledModules? })`
|
|
169
|
-
| `baseSyncPlugin({
|
|
176
|
+
| 接口 | 说明 |
|
|
177
|
+
| -------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
178
|
+
| `initBridge({ isBase, vm, iframeSelector?, handlers? })` | 初始化桥接;父应用传 `handlers`,子应用可访问 `vm.$base` |
|
|
179
|
+
| `createRegisterHandlers(getElectron?)` | 返回 `(vm) => ({ ui, cs })`,用作 `handlers` |
|
|
180
|
+
| `createMicroAppCore({ modelMap, enabledModules? })` | 返回 `{ microAppModule, microAppSrc, microAppDeployed }` |
|
|
181
|
+
| `baseSyncPlugin({ isBase, iframeSelector? })` | Vuex 插件,并挂载 `store.attachRouterSync`、`store.callMicroAppLifeCycle` |
|
|
170
182
|
|
|
171
183
|
### 参数说明
|
|
172
184
|
|
|
173
185
|
- **initBridge**
|
|
174
|
-
|
|
186
|
+
|
|
187
|
+
- `isBase`: 是否父应用
|
|
175
188
|
- `vm`: Vue 实例(子应用会在其上挂 `vm.$base`、`vm.$baseReady`)
|
|
176
189
|
- `iframeSelector`: 父应用 iframe 选择器,默认 `'#microApp'`
|
|
177
190
|
- `handlers`: 仅父应用需要,`{ [namespace]: { [method]: (params)=>any } }`
|
|
178
191
|
|
|
179
192
|
- **createRegisterHandlers**
|
|
193
|
+
|
|
180
194
|
- `getElectron`: `() => electronModule`,可选;异常或未传时 `cs` 使用 noop
|
|
181
195
|
|
|
182
196
|
- **createMicroAppCore**
|
|
197
|
+
|
|
183
198
|
- `modelMap`: `() => ({ [moduleName]: path[] })`,必填
|
|
184
199
|
- `enabledModules`: `() => string[]` 或 `string[]`,可选;缺省时从 `window.GLOBAL_CONFIG.microApp` 读取
|
|
185
200
|
|
|
186
201
|
- **baseSyncPlugin**
|
|
187
|
-
- `
|
|
202
|
+
- `isBase`: 是否父应用
|
|
188
203
|
- `iframeSelector`: 默认 `'#microApp'`
|
|
189
204
|
|
|
190
205
|
---
|
package/dist/index.esm.js
CHANGED
|
@@ -89,7 +89,7 @@ const safeClone = value => {
|
|
|
89
89
|
const createBaseObject = pending => {
|
|
90
90
|
const namespaces = {};
|
|
91
91
|
const hasProxy = typeof Proxy !== 'undefined';
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
const createMethod = (namespace, method) => {
|
|
94
94
|
return params =>
|
|
95
95
|
new Promise(resolve => {
|
|
@@ -104,7 +104,7 @@ const createBaseObject = pending => {
|
|
|
104
104
|
});
|
|
105
105
|
})
|
|
106
106
|
};
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
if (hasProxy) {
|
|
109
109
|
const base = {};
|
|
110
110
|
return new Proxy(base, {
|
|
@@ -117,33 +117,36 @@ const createBaseObject = pending => {
|
|
|
117
117
|
get(target2, method) {
|
|
118
118
|
if (typeof method === 'string') {
|
|
119
119
|
if (!namespaces[namespace][method]) {
|
|
120
|
-
namespaces[namespace][method] = createMethod(
|
|
120
|
+
namespaces[namespace][method] = createMethod(
|
|
121
|
+
namespace,
|
|
122
|
+
method
|
|
123
|
+
);
|
|
121
124
|
}
|
|
122
125
|
return namespaces[namespace][method]
|
|
123
126
|
}
|
|
124
127
|
return undefined
|
|
125
|
-
}
|
|
128
|
+
},
|
|
126
129
|
})
|
|
127
130
|
}
|
|
128
131
|
return undefined
|
|
129
|
-
}
|
|
132
|
+
},
|
|
130
133
|
})
|
|
131
134
|
} else {
|
|
132
135
|
const base = {};
|
|
133
136
|
const commonNamespaces = ['ui', 'cs'];
|
|
134
|
-
|
|
137
|
+
|
|
135
138
|
commonNamespaces.forEach(ns => {
|
|
136
139
|
namespaces[ns] = {};
|
|
137
140
|
const nsObj = {};
|
|
138
|
-
|
|
141
|
+
|
|
139
142
|
Object.defineProperty(base, ns, {
|
|
140
143
|
get() {
|
|
141
144
|
return nsObj
|
|
142
145
|
},
|
|
143
|
-
configurable: true
|
|
146
|
+
configurable: true,
|
|
144
147
|
});
|
|
145
148
|
});
|
|
146
|
-
|
|
149
|
+
|
|
147
150
|
return base
|
|
148
151
|
}
|
|
149
152
|
};
|
|
@@ -160,15 +163,15 @@ function createRegisterHandlers(getElectron) {
|
|
|
160
163
|
}
|
|
161
164
|
|
|
162
165
|
const initBridge = ({
|
|
163
|
-
|
|
166
|
+
isBase = false,
|
|
164
167
|
vm,
|
|
165
168
|
iframeSelector = '#microApp',
|
|
166
169
|
handlers = {},
|
|
167
170
|
} = {}) => {
|
|
168
|
-
const finalHandlers =
|
|
171
|
+
const finalHandlers = isBase ? handlers : Object.create(null);
|
|
169
172
|
const pending = Object.create(null);
|
|
170
173
|
|
|
171
|
-
if (!
|
|
174
|
+
if (!isBase && vm) {
|
|
172
175
|
const baseObj = createBaseObject(pending);
|
|
173
176
|
vm.$base = baseObj;
|
|
174
177
|
vm.$baseReady = true;
|
|
@@ -216,8 +219,8 @@ const initBridge = ({
|
|
|
216
219
|
if (e.origin !== window.location.origin) return
|
|
217
220
|
|
|
218
221
|
const { type } = e.data || {};
|
|
219
|
-
if (
|
|
220
|
-
if (!
|
|
222
|
+
if (isBase && type === BRIDGE$1.INVOKE) handleInvoke(e);
|
|
223
|
+
if (!isBase && type === BRIDGE$1.CALLBACK) handleCallback(e);
|
|
221
224
|
});
|
|
222
225
|
};
|
|
223
226
|
|
|
@@ -288,144 +291,210 @@ const LIFE_CYCLE = {
|
|
|
288
291
|
|
|
289
292
|
const BRIDGE = { INVOKE: 'bridge-invoke', CALLBACK: 'bridge-callback' };
|
|
290
293
|
|
|
291
|
-
const
|
|
292
|
-
const
|
|
294
|
+
const LIFE_CYCLE_SET = new Set(Object.values(LIFE_CYCLE));
|
|
295
|
+
const BRIDGE_SET = new Set(Object.values(BRIDGE));
|
|
296
|
+
const INTERNAL_SET = new Set([
|
|
297
|
+
MESSAGE.SYNC_FROM_CHILD,
|
|
298
|
+
MESSAGE.REQUEST_FROM_CHILD,
|
|
299
|
+
MESSAGE.CHILD_ROUTE_CHANGE,
|
|
300
|
+
]);
|
|
293
301
|
|
|
294
302
|
const postToChild = (iframeSelector, message) => {
|
|
295
|
-
document.querySelector(iframeSelector)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
);
|
|
303
|
+
const iframe = document.querySelector(iframeSelector);
|
|
304
|
+
if (!iframe) return
|
|
305
|
+
iframe.contentWindow?.postMessage(message, window.location.origin);
|
|
299
306
|
};
|
|
300
307
|
|
|
301
308
|
const postToParent = message => {
|
|
302
309
|
window.parent?.postMessage(message, window.location.origin);
|
|
303
310
|
};
|
|
304
311
|
|
|
305
|
-
const isLifeCycleMessage = type => LIFE_CYCLE_TYPES.includes(type);
|
|
306
|
-
|
|
307
|
-
const isBridgeMessage = type => BRIDGE_TYPES.includes(type);
|
|
308
|
-
|
|
309
|
-
const isInternalMessage = type =>
|
|
310
|
-
[
|
|
311
|
-
MESSAGE.SYNC_FROM_CHILD,
|
|
312
|
-
MESSAGE.REQUEST_FROM_CHILD,
|
|
313
|
-
MESSAGE.CHILD_ROUTE_CHANGE,
|
|
314
|
-
].includes(type);
|
|
315
|
-
|
|
316
312
|
const syncRouteFromChild = fullPath => {
|
|
317
313
|
if (typeof fullPath !== 'string') return
|
|
314
|
+
|
|
318
315
|
const { origin, pathname } = window.location;
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
316
|
+
let base = origin;
|
|
317
|
+
|
|
318
|
+
if (pathname && pathname !== '/') {
|
|
319
|
+
base = (origin + pathname).replace(/\/$/, '');
|
|
320
|
+
}
|
|
321
|
+
|
|
323
322
|
const target = `${base}/#${fullPath}`;
|
|
324
323
|
if (window.location.href !== target) {
|
|
325
324
|
window.location.href = target;
|
|
326
325
|
}
|
|
327
326
|
};
|
|
328
327
|
|
|
328
|
+
const createMessageHandlers = (
|
|
329
|
+
store,
|
|
330
|
+
isBase,
|
|
331
|
+
iframeSelector,
|
|
332
|
+
getLatestBaseState
|
|
333
|
+
) => {
|
|
334
|
+
const handlers = [];
|
|
335
|
+
|
|
336
|
+
if (!isBase) {
|
|
337
|
+
handlers.push((type, payload) => {
|
|
338
|
+
if (LIFE_CYCLE_SET.has(type)) {
|
|
339
|
+
window.__MICRO_APP_LIFECYCLE__?.[type]?.(payload);
|
|
340
|
+
return true
|
|
341
|
+
}
|
|
342
|
+
return false
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
handlers.push((type, payload, fullPath) => {
|
|
347
|
+
if (type === MESSAGE.SYNC_FROM_CHILD && isBase) {
|
|
348
|
+
store.commit('base/SYNC_STATE', payload);
|
|
349
|
+
return true
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (type === MESSAGE.SYNC_FROM_PARENT && !isBase) {
|
|
353
|
+
store.commit('base/SYNC_STATE', payload);
|
|
354
|
+
return true
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (type === MESSAGE.REQUEST_FROM_CHILD && isBase) {
|
|
358
|
+
postToChild(iframeSelector, {
|
|
359
|
+
type: MESSAGE.SYNC_FROM_PARENT,
|
|
360
|
+
payload: getLatestBaseState(),
|
|
361
|
+
});
|
|
362
|
+
return true
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (type === MESSAGE.CHILD_ROUTE_CHANGE && isBase) {
|
|
366
|
+
syncRouteFromChild(fullPath);
|
|
367
|
+
return true
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return false
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
handlers.push((type, data) => {
|
|
374
|
+
if (isBase && !INTERNAL_SET.has(type) && !BRIDGE_SET.has(type)) {
|
|
375
|
+
window.parent?.postMessage(data, '*');
|
|
376
|
+
return true
|
|
377
|
+
}
|
|
378
|
+
return false
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
return handlers
|
|
382
|
+
};
|
|
383
|
+
|
|
329
384
|
function baseSyncPlugin({
|
|
330
|
-
|
|
385
|
+
isBase = false,
|
|
331
386
|
iframeSelector = '#microApp',
|
|
332
387
|
} = {}) {
|
|
333
388
|
return store => {
|
|
334
389
|
let latestBaseState = store.state.base;
|
|
390
|
+
let isMounted = false;
|
|
335
391
|
|
|
336
|
-
|
|
337
|
-
|
|
392
|
+
const handleStateChange = () => {
|
|
393
|
+
if (!isMounted) return
|
|
394
|
+
|
|
395
|
+
const message = isBase
|
|
396
|
+
? { type: MESSAGE.SYNC_FROM_PARENT, payload: latestBaseState }
|
|
397
|
+
: { type: MESSAGE.SYNC_FROM_CHILD, payload: latestBaseState };
|
|
398
|
+
|
|
399
|
+
isBase ? postToChild(iframeSelector, message) : postToParent(message);
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const unwatch = store.watch(
|
|
403
|
+
() => store.state.base,
|
|
338
404
|
newBase => {
|
|
339
405
|
latestBaseState = newBase;
|
|
340
|
-
|
|
341
|
-
postToChild(iframeSelector, {
|
|
342
|
-
type: MESSAGE.SYNC_FROM_PARENT,
|
|
343
|
-
payload: latestBaseState,
|
|
344
|
-
});
|
|
345
|
-
} else {
|
|
346
|
-
postToParent({
|
|
347
|
-
type: MESSAGE.SYNC_FROM_CHILD,
|
|
348
|
-
payload: latestBaseState,
|
|
349
|
-
});
|
|
350
|
-
}
|
|
406
|
+
handleStateChange();
|
|
351
407
|
},
|
|
352
408
|
{ deep: true }
|
|
353
409
|
);
|
|
354
410
|
|
|
411
|
+
const messageHandlers = createMessageHandlers(
|
|
412
|
+
store,
|
|
413
|
+
isBase,
|
|
414
|
+
iframeSelector,
|
|
415
|
+
() => latestBaseState
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
const messageListener = event => {
|
|
419
|
+
if (event.origin !== window.location.origin) return
|
|
420
|
+
|
|
421
|
+
const { type, payload, fullPath } = event.data || {};
|
|
422
|
+
if (!type) return
|
|
423
|
+
|
|
424
|
+
for (const handler of messageHandlers) {
|
|
425
|
+
if (handler(type, payload, fullPath, event.data)) {
|
|
426
|
+
break
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|
|
355
431
|
store.attachRouterSync = router => {
|
|
356
|
-
if (!router ||
|
|
357
|
-
|
|
432
|
+
if (!router || isBase) return
|
|
433
|
+
|
|
434
|
+
const routeHandler = to => {
|
|
358
435
|
const parentHref = window.parent?.location?.href || '';
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
: '';
|
|
436
|
+
const hashIndex = parentHref.indexOf('#');
|
|
437
|
+
const parentFullPath =
|
|
438
|
+
hashIndex > -1 ? parentHref.slice(hashIndex + 1) : '';
|
|
362
439
|
const childFullPath = to.fullPath.startsWith('/')
|
|
363
440
|
? to.fullPath
|
|
364
441
|
: '/' + to.fullPath;
|
|
442
|
+
|
|
365
443
|
if (parentFullPath !== childFullPath) {
|
|
366
444
|
postToParent({
|
|
367
445
|
type: MESSAGE.CHILD_ROUTE_CHANGE,
|
|
368
446
|
fullPath: to.fullPath,
|
|
369
447
|
});
|
|
370
448
|
}
|
|
371
|
-
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
router.afterEach(routeHandler);
|
|
372
452
|
};
|
|
373
453
|
|
|
374
454
|
store.callMicroAppLifeCycle = (type, payload) => {
|
|
375
|
-
if (!
|
|
376
|
-
if (!isLifeCycleMessage(type)) return
|
|
455
|
+
if (!isBase || !LIFE_CYCLE_SET.has(type)) return
|
|
377
456
|
|
|
378
|
-
postToChild(iframeSelector, {
|
|
379
|
-
type,
|
|
380
|
-
payload,
|
|
381
|
-
});
|
|
457
|
+
postToChild(iframeSelector, { type, payload });
|
|
382
458
|
};
|
|
383
459
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if (!isParent && isLifeCycleMessage(type)) {
|
|
389
|
-
window.__MICRO_APP_LIFECYCLE__?.[type]?.(payload);
|
|
390
|
-
return
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (isParent && type === MESSAGE.SYNC_FROM_CHILD) {
|
|
394
|
-
store.commit('base/SYNC_STATE', payload);
|
|
395
|
-
return
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (!isParent && type === MESSAGE.SYNC_FROM_PARENT) {
|
|
399
|
-
store.commit('base/SYNC_STATE', payload);
|
|
400
|
-
return
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (isParent && type === MESSAGE.REQUEST_FROM_CHILD) {
|
|
404
|
-
postToChild(iframeSelector, {
|
|
405
|
-
type: MESSAGE.SYNC_FROM_PARENT,
|
|
406
|
-
payload: latestBaseState,
|
|
407
|
-
});
|
|
408
|
-
return
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
if (isParent && type === MESSAGE.CHILD_ROUTE_CHANGE) {
|
|
412
|
-
syncRouteFromChild(fullPath);
|
|
413
|
-
return
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (isParent && !isInternalMessage(type) && !isBridgeMessage(type)) {
|
|
417
|
-
window.parent?.postMessage(event.data || {}, '*');
|
|
418
|
-
}
|
|
460
|
+
store.destroy = () => {
|
|
461
|
+
window.removeEventListener('message', messageListener);
|
|
462
|
+
unwatch?.();
|
|
463
|
+
isMounted = false;
|
|
419
464
|
};
|
|
420
465
|
|
|
421
|
-
window.addEventListener('message',
|
|
466
|
+
window.addEventListener('message', messageListener);
|
|
422
467
|
|
|
423
|
-
if (!
|
|
424
|
-
|
|
468
|
+
if (!isBase && window.parent) {
|
|
469
|
+
const requestTimer = setTimeout(() => {
|
|
470
|
+
postToParent({ type: MESSAGE.REQUEST_FROM_CHILD });
|
|
471
|
+
isMounted = true;
|
|
472
|
+
clearTimeout(requestTimer);
|
|
473
|
+
}, 0);
|
|
474
|
+
} else {
|
|
475
|
+
isMounted = true;
|
|
425
476
|
}
|
|
477
|
+
|
|
478
|
+
return store
|
|
426
479
|
}
|
|
427
480
|
}
|
|
428
481
|
|
|
429
|
-
|
|
482
|
+
function syncState(watch = {}) {
|
|
483
|
+
return function SYNC_STATE(state, payload) {
|
|
484
|
+
if (!payload || typeof payload !== 'object') return
|
|
485
|
+
|
|
486
|
+
Object.keys(watch).forEach(key => {
|
|
487
|
+
if (state[key] !== payload[key] && typeof watch[key] === 'function')
|
|
488
|
+
watch[key]({
|
|
489
|
+
store: this,
|
|
490
|
+
value: payload[key],
|
|
491
|
+
valueOld: state[key],
|
|
492
|
+
});
|
|
493
|
+
});
|
|
494
|
+
Object.keys(payload).forEach(key => {
|
|
495
|
+
if (state[key] !== payload[key]) state[key] = payload[key];
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
430
499
|
|
|
431
|
-
export { baseSyncPlugin, createMicroAppCore, createRegisterHandlers,
|
|
500
|
+
export { baseSyncPlugin, createMicroAppCore, createRegisterHandlers, initBridge, syncState };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var uiHandler = vm => ({
|
|
6
4
|
$message: (...args) => vm.$message(...args),
|
|
7
5
|
$success: msg => vm.$message.success(msg),
|
|
@@ -93,7 +91,7 @@ const safeClone = value => {
|
|
|
93
91
|
const createBaseObject = pending => {
|
|
94
92
|
const namespaces = {};
|
|
95
93
|
const hasProxy = typeof Proxy !== 'undefined';
|
|
96
|
-
|
|
94
|
+
|
|
97
95
|
const createMethod = (namespace, method) => {
|
|
98
96
|
return params =>
|
|
99
97
|
new Promise(resolve => {
|
|
@@ -108,7 +106,7 @@ const createBaseObject = pending => {
|
|
|
108
106
|
});
|
|
109
107
|
})
|
|
110
108
|
};
|
|
111
|
-
|
|
109
|
+
|
|
112
110
|
if (hasProxy) {
|
|
113
111
|
const base = {};
|
|
114
112
|
return new Proxy(base, {
|
|
@@ -121,33 +119,36 @@ const createBaseObject = pending => {
|
|
|
121
119
|
get(target2, method) {
|
|
122
120
|
if (typeof method === 'string') {
|
|
123
121
|
if (!namespaces[namespace][method]) {
|
|
124
|
-
namespaces[namespace][method] = createMethod(
|
|
122
|
+
namespaces[namespace][method] = createMethod(
|
|
123
|
+
namespace,
|
|
124
|
+
method
|
|
125
|
+
);
|
|
125
126
|
}
|
|
126
127
|
return namespaces[namespace][method]
|
|
127
128
|
}
|
|
128
129
|
return undefined
|
|
129
|
-
}
|
|
130
|
+
},
|
|
130
131
|
})
|
|
131
132
|
}
|
|
132
133
|
return undefined
|
|
133
|
-
}
|
|
134
|
+
},
|
|
134
135
|
})
|
|
135
136
|
} else {
|
|
136
137
|
const base = {};
|
|
137
138
|
const commonNamespaces = ['ui', 'cs'];
|
|
138
|
-
|
|
139
|
+
|
|
139
140
|
commonNamespaces.forEach(ns => {
|
|
140
141
|
namespaces[ns] = {};
|
|
141
142
|
const nsObj = {};
|
|
142
|
-
|
|
143
|
+
|
|
143
144
|
Object.defineProperty(base, ns, {
|
|
144
145
|
get() {
|
|
145
146
|
return nsObj
|
|
146
147
|
},
|
|
147
|
-
configurable: true
|
|
148
|
+
configurable: true,
|
|
148
149
|
});
|
|
149
150
|
});
|
|
150
|
-
|
|
151
|
+
|
|
151
152
|
return base
|
|
152
153
|
}
|
|
153
154
|
};
|
|
@@ -164,15 +165,15 @@ function createRegisterHandlers(getElectron) {
|
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
const initBridge = ({
|
|
167
|
-
|
|
168
|
+
isBase = false,
|
|
168
169
|
vm,
|
|
169
170
|
iframeSelector = '#microApp',
|
|
170
171
|
handlers = {},
|
|
171
172
|
} = {}) => {
|
|
172
|
-
const finalHandlers =
|
|
173
|
+
const finalHandlers = isBase ? handlers : Object.create(null);
|
|
173
174
|
const pending = Object.create(null);
|
|
174
175
|
|
|
175
|
-
if (!
|
|
176
|
+
if (!isBase && vm) {
|
|
176
177
|
const baseObj = createBaseObject(pending);
|
|
177
178
|
vm.$base = baseObj;
|
|
178
179
|
vm.$baseReady = true;
|
|
@@ -220,8 +221,8 @@ const initBridge = ({
|
|
|
220
221
|
if (e.origin !== window.location.origin) return
|
|
221
222
|
|
|
222
223
|
const { type } = e.data || {};
|
|
223
|
-
if (
|
|
224
|
-
if (!
|
|
224
|
+
if (isBase && type === BRIDGE$1.INVOKE) handleInvoke(e);
|
|
225
|
+
if (!isBase && type === BRIDGE$1.CALLBACK) handleCallback(e);
|
|
225
226
|
});
|
|
226
227
|
};
|
|
227
228
|
|
|
@@ -292,148 +293,214 @@ const LIFE_CYCLE = {
|
|
|
292
293
|
|
|
293
294
|
const BRIDGE = { INVOKE: 'bridge-invoke', CALLBACK: 'bridge-callback' };
|
|
294
295
|
|
|
295
|
-
const
|
|
296
|
-
const
|
|
296
|
+
const LIFE_CYCLE_SET = new Set(Object.values(LIFE_CYCLE));
|
|
297
|
+
const BRIDGE_SET = new Set(Object.values(BRIDGE));
|
|
298
|
+
const INTERNAL_SET = new Set([
|
|
299
|
+
MESSAGE.SYNC_FROM_CHILD,
|
|
300
|
+
MESSAGE.REQUEST_FROM_CHILD,
|
|
301
|
+
MESSAGE.CHILD_ROUTE_CHANGE,
|
|
302
|
+
]);
|
|
297
303
|
|
|
298
304
|
const postToChild = (iframeSelector, message) => {
|
|
299
|
-
document.querySelector(iframeSelector)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
305
|
+
const iframe = document.querySelector(iframeSelector);
|
|
306
|
+
if (!iframe) return
|
|
307
|
+
iframe.contentWindow?.postMessage(message, window.location.origin);
|
|
303
308
|
};
|
|
304
309
|
|
|
305
310
|
const postToParent = message => {
|
|
306
311
|
window.parent?.postMessage(message, window.location.origin);
|
|
307
312
|
};
|
|
308
313
|
|
|
309
|
-
const isLifeCycleMessage = type => LIFE_CYCLE_TYPES.includes(type);
|
|
310
|
-
|
|
311
|
-
const isBridgeMessage = type => BRIDGE_TYPES.includes(type);
|
|
312
|
-
|
|
313
|
-
const isInternalMessage = type =>
|
|
314
|
-
[
|
|
315
|
-
MESSAGE.SYNC_FROM_CHILD,
|
|
316
|
-
MESSAGE.REQUEST_FROM_CHILD,
|
|
317
|
-
MESSAGE.CHILD_ROUTE_CHANGE,
|
|
318
|
-
].includes(type);
|
|
319
|
-
|
|
320
314
|
const syncRouteFromChild = fullPath => {
|
|
321
315
|
if (typeof fullPath !== 'string') return
|
|
316
|
+
|
|
322
317
|
const { origin, pathname } = window.location;
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
318
|
+
let base = origin;
|
|
319
|
+
|
|
320
|
+
if (pathname && pathname !== '/') {
|
|
321
|
+
base = (origin + pathname).replace(/\/$/, '');
|
|
322
|
+
}
|
|
323
|
+
|
|
327
324
|
const target = `${base}/#${fullPath}`;
|
|
328
325
|
if (window.location.href !== target) {
|
|
329
326
|
window.location.href = target;
|
|
330
327
|
}
|
|
331
328
|
};
|
|
332
329
|
|
|
330
|
+
const createMessageHandlers = (
|
|
331
|
+
store,
|
|
332
|
+
isBase,
|
|
333
|
+
iframeSelector,
|
|
334
|
+
getLatestBaseState
|
|
335
|
+
) => {
|
|
336
|
+
const handlers = [];
|
|
337
|
+
|
|
338
|
+
if (!isBase) {
|
|
339
|
+
handlers.push((type, payload) => {
|
|
340
|
+
if (LIFE_CYCLE_SET.has(type)) {
|
|
341
|
+
window.__MICRO_APP_LIFECYCLE__?.[type]?.(payload);
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
return false
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
handlers.push((type, payload, fullPath) => {
|
|
349
|
+
if (type === MESSAGE.SYNC_FROM_CHILD && isBase) {
|
|
350
|
+
store.commit('base/SYNC_STATE', payload);
|
|
351
|
+
return true
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (type === MESSAGE.SYNC_FROM_PARENT && !isBase) {
|
|
355
|
+
store.commit('base/SYNC_STATE', payload);
|
|
356
|
+
return true
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (type === MESSAGE.REQUEST_FROM_CHILD && isBase) {
|
|
360
|
+
postToChild(iframeSelector, {
|
|
361
|
+
type: MESSAGE.SYNC_FROM_PARENT,
|
|
362
|
+
payload: getLatestBaseState(),
|
|
363
|
+
});
|
|
364
|
+
return true
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (type === MESSAGE.CHILD_ROUTE_CHANGE && isBase) {
|
|
368
|
+
syncRouteFromChild(fullPath);
|
|
369
|
+
return true
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return false
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
handlers.push((type, data) => {
|
|
376
|
+
if (isBase && !INTERNAL_SET.has(type) && !BRIDGE_SET.has(type)) {
|
|
377
|
+
window.parent?.postMessage(data, '*');
|
|
378
|
+
return true
|
|
379
|
+
}
|
|
380
|
+
return false
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
return handlers
|
|
384
|
+
};
|
|
385
|
+
|
|
333
386
|
function baseSyncPlugin({
|
|
334
|
-
|
|
387
|
+
isBase = false,
|
|
335
388
|
iframeSelector = '#microApp',
|
|
336
389
|
} = {}) {
|
|
337
390
|
return store => {
|
|
338
391
|
let latestBaseState = store.state.base;
|
|
392
|
+
let isMounted = false;
|
|
393
|
+
|
|
394
|
+
const handleStateChange = () => {
|
|
395
|
+
if (!isMounted) return
|
|
396
|
+
|
|
397
|
+
const message = isBase
|
|
398
|
+
? { type: MESSAGE.SYNC_FROM_PARENT, payload: latestBaseState }
|
|
399
|
+
: { type: MESSAGE.SYNC_FROM_CHILD, payload: latestBaseState };
|
|
400
|
+
|
|
401
|
+
isBase ? postToChild(iframeSelector, message) : postToParent(message);
|
|
402
|
+
};
|
|
339
403
|
|
|
340
|
-
store.watch(
|
|
341
|
-
|
|
404
|
+
const unwatch = store.watch(
|
|
405
|
+
() => store.state.base,
|
|
342
406
|
newBase => {
|
|
343
407
|
latestBaseState = newBase;
|
|
344
|
-
|
|
345
|
-
postToChild(iframeSelector, {
|
|
346
|
-
type: MESSAGE.SYNC_FROM_PARENT,
|
|
347
|
-
payload: latestBaseState,
|
|
348
|
-
});
|
|
349
|
-
} else {
|
|
350
|
-
postToParent({
|
|
351
|
-
type: MESSAGE.SYNC_FROM_CHILD,
|
|
352
|
-
payload: latestBaseState,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
408
|
+
handleStateChange();
|
|
355
409
|
},
|
|
356
410
|
{ deep: true }
|
|
357
411
|
);
|
|
358
412
|
|
|
413
|
+
const messageHandlers = createMessageHandlers(
|
|
414
|
+
store,
|
|
415
|
+
isBase,
|
|
416
|
+
iframeSelector,
|
|
417
|
+
() => latestBaseState
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
const messageListener = event => {
|
|
421
|
+
if (event.origin !== window.location.origin) return
|
|
422
|
+
|
|
423
|
+
const { type, payload, fullPath } = event.data || {};
|
|
424
|
+
if (!type) return
|
|
425
|
+
|
|
426
|
+
for (const handler of messageHandlers) {
|
|
427
|
+
if (handler(type, payload, fullPath, event.data)) {
|
|
428
|
+
break
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
359
433
|
store.attachRouterSync = router => {
|
|
360
|
-
if (!router ||
|
|
361
|
-
|
|
434
|
+
if (!router || isBase) return
|
|
435
|
+
|
|
436
|
+
const routeHandler = to => {
|
|
362
437
|
const parentHref = window.parent?.location?.href || '';
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
: '';
|
|
438
|
+
const hashIndex = parentHref.indexOf('#');
|
|
439
|
+
const parentFullPath =
|
|
440
|
+
hashIndex > -1 ? parentHref.slice(hashIndex + 1) : '';
|
|
366
441
|
const childFullPath = to.fullPath.startsWith('/')
|
|
367
442
|
? to.fullPath
|
|
368
443
|
: '/' + to.fullPath;
|
|
444
|
+
|
|
369
445
|
if (parentFullPath !== childFullPath) {
|
|
370
446
|
postToParent({
|
|
371
447
|
type: MESSAGE.CHILD_ROUTE_CHANGE,
|
|
372
448
|
fullPath: to.fullPath,
|
|
373
449
|
});
|
|
374
450
|
}
|
|
375
|
-
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
router.afterEach(routeHandler);
|
|
376
454
|
};
|
|
377
455
|
|
|
378
456
|
store.callMicroAppLifeCycle = (type, payload) => {
|
|
379
|
-
if (!
|
|
380
|
-
if (!isLifeCycleMessage(type)) return
|
|
457
|
+
if (!isBase || !LIFE_CYCLE_SET.has(type)) return
|
|
381
458
|
|
|
382
|
-
postToChild(iframeSelector, {
|
|
383
|
-
type,
|
|
384
|
-
payload,
|
|
385
|
-
});
|
|
459
|
+
postToChild(iframeSelector, { type, payload });
|
|
386
460
|
};
|
|
387
461
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (!isParent && isLifeCycleMessage(type)) {
|
|
393
|
-
window.__MICRO_APP_LIFECYCLE__?.[type]?.(payload);
|
|
394
|
-
return
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
if (isParent && type === MESSAGE.SYNC_FROM_CHILD) {
|
|
398
|
-
store.commit('base/SYNC_STATE', payload);
|
|
399
|
-
return
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
if (!isParent && type === MESSAGE.SYNC_FROM_PARENT) {
|
|
403
|
-
store.commit('base/SYNC_STATE', payload);
|
|
404
|
-
return
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
if (isParent && type === MESSAGE.REQUEST_FROM_CHILD) {
|
|
408
|
-
postToChild(iframeSelector, {
|
|
409
|
-
type: MESSAGE.SYNC_FROM_PARENT,
|
|
410
|
-
payload: latestBaseState,
|
|
411
|
-
});
|
|
412
|
-
return
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (isParent && type === MESSAGE.CHILD_ROUTE_CHANGE) {
|
|
416
|
-
syncRouteFromChild(fullPath);
|
|
417
|
-
return
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (isParent && !isInternalMessage(type) && !isBridgeMessage(type)) {
|
|
421
|
-
window.parent?.postMessage(event.data || {}, '*');
|
|
422
|
-
}
|
|
462
|
+
store.destroy = () => {
|
|
463
|
+
window.removeEventListener('message', messageListener);
|
|
464
|
+
unwatch?.();
|
|
465
|
+
isMounted = false;
|
|
423
466
|
};
|
|
424
467
|
|
|
425
|
-
window.addEventListener('message',
|
|
468
|
+
window.addEventListener('message', messageListener);
|
|
426
469
|
|
|
427
|
-
if (!
|
|
428
|
-
|
|
470
|
+
if (!isBase && window.parent) {
|
|
471
|
+
const requestTimer = setTimeout(() => {
|
|
472
|
+
postToParent({ type: MESSAGE.REQUEST_FROM_CHILD });
|
|
473
|
+
isMounted = true;
|
|
474
|
+
clearTimeout(requestTimer);
|
|
475
|
+
}, 0);
|
|
476
|
+
} else {
|
|
477
|
+
isMounted = true;
|
|
429
478
|
}
|
|
479
|
+
|
|
480
|
+
return store
|
|
430
481
|
}
|
|
431
482
|
}
|
|
432
483
|
|
|
433
|
-
|
|
484
|
+
function syncState(watch = {}) {
|
|
485
|
+
return function SYNC_STATE(state, payload) {
|
|
486
|
+
if (!payload || typeof payload !== 'object') return
|
|
487
|
+
|
|
488
|
+
Object.keys(watch).forEach(key => {
|
|
489
|
+
if (state[key] !== payload[key] && typeof watch[key] === 'function')
|
|
490
|
+
watch[key]({
|
|
491
|
+
store: this,
|
|
492
|
+
value: payload[key],
|
|
493
|
+
valueOld: state[key],
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
Object.keys(payload).forEach(key => {
|
|
497
|
+
if (state[key] !== payload[key]) state[key] = payload[key];
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
434
501
|
|
|
435
502
|
exports.baseSyncPlugin = baseSyncPlugin;
|
|
436
503
|
exports.createMicroAppCore = createMicroAppCore;
|
|
437
504
|
exports.createRegisterHandlers = createRegisterHandlers;
|
|
438
|
-
exports.default = index;
|
|
439
505
|
exports.initBridge = initBridge;
|
|
506
|
+
exports.syncState = syncState;
|