@micro-zoe/micro-app 1.0.0-beta.6 → 1.0.0-rc.0
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/lib/index.d.ts +1 -0
- package/lib/index.esm.js +150 -78
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/typings/global.d.ts +12 -8
package/lib/index.d.ts
CHANGED
|
@@ -62,6 +62,7 @@ declare module '@micro-zoe/micro-app/micro_app' {
|
|
|
62
62
|
export function renderApp(options: RenderAppOptions): Promise<boolean>;
|
|
63
63
|
export class MicroApp extends EventCenterForBaseApp implements MicroAppBaseType {
|
|
64
64
|
tagName: string;
|
|
65
|
+
hasInit: boolean;
|
|
65
66
|
options: OptionsType;
|
|
66
67
|
router: Router;
|
|
67
68
|
preFetch: typeof preFetch;
|
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-
|
|
1
|
+
const version = '1.0.0-rc.0';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -357,20 +357,23 @@ function pureCreateElement(tagName, options) {
|
|
|
357
357
|
* @param deep deep clone or transfer dom
|
|
358
358
|
*/
|
|
359
359
|
function cloneContainer(target, origin, deep) {
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
fragment.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
360
|
+
// 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
|
|
361
|
+
if (origin) {
|
|
362
|
+
target.innerHTML = '';
|
|
363
|
+
if (deep) {
|
|
364
|
+
// TODO: ShadowRoot兼容,ShadowRoot不能直接使用cloneNode
|
|
365
|
+
const clonedNode = origin.cloneNode(true);
|
|
366
|
+
const fragment = document.createDocumentFragment();
|
|
367
|
+
Array.from(clonedNode.childNodes).forEach((node) => {
|
|
368
|
+
fragment.appendChild(node);
|
|
369
|
+
});
|
|
370
|
+
target.appendChild(fragment);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
Array.from(origin.childNodes).forEach((node) => {
|
|
374
|
+
target.appendChild(node);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
374
377
|
}
|
|
375
378
|
return target;
|
|
376
379
|
}
|
|
@@ -606,10 +609,11 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
606
609
|
* @param detail event detail
|
|
607
610
|
*/
|
|
608
611
|
function dispatchCustomEventToMicroApp(app, eventName, detail = {}) {
|
|
612
|
+
var _a;
|
|
609
613
|
const event = new CustomEvent(eventName, {
|
|
610
614
|
detail,
|
|
611
615
|
});
|
|
612
|
-
app.sandBox.microAppWindow.dispatchEvent(event);
|
|
616
|
+
(_a = app.sandBox) === null || _a === void 0 ? void 0 : _a.microAppWindow.dispatchEvent(event);
|
|
613
617
|
}
|
|
614
618
|
|
|
615
619
|
/**
|
|
@@ -1394,6 +1398,7 @@ var appStates;
|
|
|
1394
1398
|
appStates["CREATED"] = "created";
|
|
1395
1399
|
appStates["LOADING"] = "loading";
|
|
1396
1400
|
appStates["LOAD_FAILED"] = "load_failed";
|
|
1401
|
+
appStates["BEFORE_MOUNT"] = "before_mount";
|
|
1397
1402
|
appStates["MOUNTING"] = "mounting";
|
|
1398
1403
|
appStates["MOUNTED"] = "mounted";
|
|
1399
1404
|
appStates["UNMOUNT"] = "unmount";
|
|
@@ -3509,7 +3514,7 @@ function isEffectiveApp(appName) {
|
|
|
3509
3514
|
const app = appInstanceMap.get(appName);
|
|
3510
3515
|
/**
|
|
3511
3516
|
* !!(app && !app.isPrefetch && !app.isHidden())
|
|
3512
|
-
*
|
|
3517
|
+
* NOTE: 隐藏的keep-alive应用暂时不作为无效应用,原因如下
|
|
3513
3518
|
* 1、隐藏后才执行去除浏览器上的微应用的路由信息的操作,导致微应用的路由信息无法去除
|
|
3514
3519
|
* 2、如果保持隐藏应用内部正常跳转,阻止同步路由信息到浏览器,这样理论上是好的,但是对于location跳转改如何处理?location跳转是基于修改浏览器地址后发送popstate事件实现的,所以应该是在隐藏后不支持通过location进行跳转
|
|
3515
3520
|
*/
|
|
@@ -3865,6 +3870,39 @@ function createRouterApi() {
|
|
|
3865
3870
|
// clear element scope after navigate
|
|
3866
3871
|
removeDomScope();
|
|
3867
3872
|
}
|
|
3873
|
+
/**
|
|
3874
|
+
* navigation handler
|
|
3875
|
+
* @param appName app.name
|
|
3876
|
+
* @param app app instance
|
|
3877
|
+
* @param to router target options
|
|
3878
|
+
* @param replace use router.replace?
|
|
3879
|
+
*/
|
|
3880
|
+
function handleNavigate(appName, app, to, replace) {
|
|
3881
|
+
const microLocation = app.sandBox.proxyWindow.location;
|
|
3882
|
+
const targetLocation = createURL(to.path, microLocation.href);
|
|
3883
|
+
// Only get path data, even if the origin is different from microApp
|
|
3884
|
+
const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash;
|
|
3885
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3886
|
+
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
3887
|
+
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
3888
|
+
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
3889
|
+
/**
|
|
3890
|
+
* TODO:
|
|
3891
|
+
* 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明
|
|
3892
|
+
* 2. 关闭虚拟路由时跳转方式不同:1、基座跳转但不发送popstate事件 2、控制子应用更新location,内部发送popstate事件。
|
|
3893
|
+
* 核心思路:减小对基座的影响(子应用跳转不向基座发送popstate事件,其他操作一致),但这是必要的吗,只是多了一个触发popstate的操作
|
|
3894
|
+
* 路由优化方案有两种:
|
|
3895
|
+
* 1、减少对基座的影响,主要是解决vue循环刷新的问题
|
|
3896
|
+
* 2、全局发送popstate事件,解决主、子都是vue3的冲突问题
|
|
3897
|
+
* 两者选一个吧,如果选2,则下面这两行代码可以去掉
|
|
3898
|
+
* NOTE1: history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高
|
|
3899
|
+
* NOTE2: 关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。
|
|
3900
|
+
*/
|
|
3901
|
+
if (isRouterModeCustom(appName)) {
|
|
3902
|
+
updateMicroLocationWithEvent(appName, targetFullPath);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3868
3906
|
/**
|
|
3869
3907
|
* create method of router.push/replace
|
|
3870
3908
|
* NOTE:
|
|
@@ -3883,33 +3921,16 @@ function createRouterApi() {
|
|
|
3883
3921
|
* 1. prerender app or hidden keep-alive app clear and record popstate event, so we cannot control app jump through the API
|
|
3884
3922
|
* 2. disable memory-router
|
|
3885
3923
|
*/
|
|
3924
|
+
/**
|
|
3925
|
+
* TODO: 子应用开始渲染但是还没渲染完成
|
|
3926
|
+
* 1、调用跳转改如何处理
|
|
3927
|
+
* 2、iframe的沙箱还没初始化时执行跳转报错,如何处理。。。
|
|
3928
|
+
* 3、hidden app 是否支持跳转
|
|
3929
|
+
*/
|
|
3886
3930
|
if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) {
|
|
3887
3931
|
const app = appInstanceMap.get(appName);
|
|
3888
|
-
const
|
|
3889
|
-
|
|
3890
|
-
// Only get path data, even if the origin is different from microApp
|
|
3891
|
-
const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash;
|
|
3892
|
-
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3893
|
-
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
3894
|
-
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
3895
|
-
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
3896
|
-
/**
|
|
3897
|
-
* TODO:
|
|
3898
|
-
* 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明
|
|
3899
|
-
* 2. 关闭虚拟路由时跳转方式不同:1、基座跳转但不发送popstate事件 2、控制子应用更新location,内部发送popstate事件。
|
|
3900
|
-
* 补充:
|
|
3901
|
-
* 核心思路:减小对基座的影响(就是子应用跳转不向基座发送popstate事件,其他操作一致),但这是必要的吗,只是多了一个触发popstate的操作
|
|
3902
|
-
* 未来的思路有两种:
|
|
3903
|
-
* 1、减少对基座的影响,主要是解决vue循环刷新的问题
|
|
3904
|
-
* 2、全局发送popstate事件,解决主、子都是vue3的冲突问题
|
|
3905
|
-
* 两者选一个吧,如果选2,则下面这两行代码可以去掉
|
|
3906
|
-
* 要不这样吧,history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高
|
|
3907
|
-
* 如果关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。
|
|
3908
|
-
*/
|
|
3909
|
-
if (isRouterModeCustom(appName)) {
|
|
3910
|
-
updateMicroLocationWithEvent(appName, targetFullPath);
|
|
3911
|
-
}
|
|
3912
|
-
}
|
|
3932
|
+
const navigateAction = () => handleNavigate(appName, app, to, replace);
|
|
3933
|
+
app.iframe ? app.sandBox.sandboxReady.then(navigateAction) : navigateAction();
|
|
3913
3934
|
}
|
|
3914
3935
|
else {
|
|
3915
3936
|
logWarn('navigation failed, app does not exist or is inactive');
|
|
@@ -4639,6 +4660,8 @@ class WithSandBox {
|
|
|
4639
4660
|
this.adapter = new Adapter();
|
|
4640
4661
|
// get scopeProperties and escapeProperties from plugins
|
|
4641
4662
|
this.getSpecialProperties(appName);
|
|
4663
|
+
// create location, history for child app
|
|
4664
|
+
this.patchRouter(appName, url, this.microAppWindow);
|
|
4642
4665
|
// patch window of child app
|
|
4643
4666
|
this.windowEffect = patchWindow(appName, this.microAppWindow, this);
|
|
4644
4667
|
// patch document of child app
|
|
@@ -4658,10 +4681,6 @@ class WithSandBox {
|
|
|
4658
4681
|
return;
|
|
4659
4682
|
this.active = true;
|
|
4660
4683
|
/* --- memory router part --- start */
|
|
4661
|
-
// create location, history for child app
|
|
4662
|
-
if (isUndefined(this.microAppWindow.location)) {
|
|
4663
|
-
this.setMicroAppRouter(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, this.microAppWindow);
|
|
4664
|
-
}
|
|
4665
4684
|
// update microLocation, attach route info to browser url
|
|
4666
4685
|
this.initRouteState(defaultPage);
|
|
4667
4686
|
// unique listener of popstate event for sub app
|
|
@@ -4744,6 +4763,8 @@ class WithSandBox {
|
|
|
4744
4763
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
4745
4764
|
microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
4746
4765
|
microAppWindow.__MICRO_APP_UMD_MODE__ = false;
|
|
4766
|
+
microAppWindow.__MICRO_APP_SANDBOX__ = this;
|
|
4767
|
+
microAppWindow.__MICRO_APP_SANDBOX_TYPE__ = 'with';
|
|
4747
4768
|
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
4748
4769
|
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
4749
4770
|
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
@@ -4983,7 +5004,7 @@ class WithSandBox {
|
|
|
4983
5004
|
});
|
|
4984
5005
|
}
|
|
4985
5006
|
// set location & history for memory router
|
|
4986
|
-
|
|
5007
|
+
patchRouter(appName, url, microAppWindow) {
|
|
4987
5008
|
const { microLocation, microHistory } = createMicroRouter(appName, url);
|
|
4988
5009
|
rawDefineProperties(microAppWindow, {
|
|
4989
5010
|
location: {
|
|
@@ -5036,7 +5057,7 @@ class WithSandBox {
|
|
|
5036
5057
|
}
|
|
5037
5058
|
WithSandBox.activeCount = 0; // number of active sandbox
|
|
5038
5059
|
|
|
5039
|
-
function
|
|
5060
|
+
function patchRouter(appName, url, microAppWindow, browserHost) {
|
|
5040
5061
|
const childStaticLocation = new URL(url);
|
|
5041
5062
|
const childHost = childStaticLocation.protocol + '//' + childStaticLocation.host;
|
|
5042
5063
|
const childFullPath = childStaticLocation.pathname + childStaticLocation.search + childStaticLocation.hash;
|
|
@@ -5275,6 +5296,15 @@ function patchDocumentPrototype(appName, microAppWindow) {
|
|
|
5275
5296
|
const rawMicroGetElementsByClassName = microRootDocument.prototype.getElementsByClassName;
|
|
5276
5297
|
const rawMicroGetElementsByTagName = microRootDocument.prototype.getElementsByTagName;
|
|
5277
5298
|
const rawMicroGetElementsByName = microRootDocument.prototype.getElementsByName;
|
|
5299
|
+
const rawMicroElementFromPoint = microRootDocument.prototype.elementFromPoint;
|
|
5300
|
+
const rawMicroCaretRangeFromPoint = microRootDocument.prototype.caretRangeFromPoint;
|
|
5301
|
+
microRootDocument.prototype.caretRangeFromPoint = function caretRangeFromPoint(x, y) {
|
|
5302
|
+
// 这里this指向document才可以获取到子应用的document实例,range才可以被成功生成
|
|
5303
|
+
const element = rawMicroElementFromPoint.call(rawDocument, x, y);
|
|
5304
|
+
const range = rawMicroCaretRangeFromPoint.call(rawDocument, x, y);
|
|
5305
|
+
updateElementInfo(element, appName);
|
|
5306
|
+
return range;
|
|
5307
|
+
};
|
|
5278
5308
|
microRootDocument.prototype.createElement = function createElement(tagName, options) {
|
|
5279
5309
|
const element = rawMicroCreateElement.call(this, tagName, options);
|
|
5280
5310
|
return updateElementInfo(element, appName);
|
|
@@ -5790,13 +5820,12 @@ class IframeSandbox {
|
|
|
5790
5820
|
this.deleteIframeElement = this.createIframeElement(appName, browserHost);
|
|
5791
5821
|
this.microAppWindow = this.iframe.contentWindow;
|
|
5792
5822
|
this.patchIframe(this.microAppWindow, (resolve) => {
|
|
5793
|
-
// TODO: 优化代码
|
|
5794
5823
|
// create new html to iframe
|
|
5795
5824
|
this.createIframeTemplate(this.microAppWindow);
|
|
5796
5825
|
// get escapeProperties from plugins
|
|
5797
5826
|
this.getSpecialProperties(appName);
|
|
5798
5827
|
// patch location & history of child app
|
|
5799
|
-
this.proxyLocation =
|
|
5828
|
+
this.proxyLocation = patchRouter(appName, url, this.microAppWindow, browserHost);
|
|
5800
5829
|
// patch window of child app
|
|
5801
5830
|
this.windowEffect = patchWindow$1(appName, this.microAppWindow, this);
|
|
5802
5831
|
// patch document of child app
|
|
@@ -5807,9 +5836,9 @@ class IframeSandbox {
|
|
|
5807
5836
|
* create static properties
|
|
5808
5837
|
* NOTE:
|
|
5809
5838
|
* 1. execute as early as possible
|
|
5810
|
-
* 2. run after
|
|
5839
|
+
* 2. run after patchRouter & createProxyWindow
|
|
5811
5840
|
*/
|
|
5812
|
-
this.initStaticGlobalKeys(appName, url);
|
|
5841
|
+
this.initStaticGlobalKeys(appName, url, this.microAppWindow);
|
|
5813
5842
|
resolve();
|
|
5814
5843
|
});
|
|
5815
5844
|
}
|
|
@@ -5914,22 +5943,23 @@ class IframeSandbox {
|
|
|
5914
5943
|
* create static properties
|
|
5915
5944
|
* NOTE:
|
|
5916
5945
|
* 1. execute as early as possible
|
|
5917
|
-
* 2. run after
|
|
5946
|
+
* 2. run after patchRouter & createProxyWindow
|
|
5918
5947
|
*/
|
|
5919
|
-
initStaticGlobalKeys(appName, url) {
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5948
|
+
initStaticGlobalKeys(appName, url, microAppWindow) {
|
|
5949
|
+
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
5950
|
+
microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
5951
|
+
microAppWindow.__MICRO_APP_URL__ = url;
|
|
5952
|
+
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
5953
|
+
microAppWindow.__MICRO_APP_BASE_ROUTE__ = '';
|
|
5954
|
+
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
5955
|
+
microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
5956
|
+
microAppWindow.__MICRO_APP_UMD_MODE__ = false;
|
|
5957
|
+
microAppWindow.__MICRO_APP_PROXY_WINDOW__ = this.proxyWindow;
|
|
5958
|
+
microAppWindow.__MICRO_APP_SANDBOX__ = this;
|
|
5959
|
+
microAppWindow.__MICRO_APP_SANDBOX_TYPE__ = 'iframe';
|
|
5960
|
+
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
5961
|
+
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
5962
|
+
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
5933
5963
|
removeDomScope,
|
|
5934
5964
|
pureCreateElement,
|
|
5935
5965
|
location: this.proxyLocation,
|
|
@@ -6026,7 +6056,12 @@ class IframeSandbox {
|
|
|
6026
6056
|
(function iframeLocationReady() {
|
|
6027
6057
|
setTimeout(() => {
|
|
6028
6058
|
try {
|
|
6029
|
-
|
|
6059
|
+
/**
|
|
6060
|
+
* NOTE:
|
|
6061
|
+
* 1. In browser, iframe document will be recreated after iframe initial
|
|
6062
|
+
* 2. In jest, iframe document is always the same
|
|
6063
|
+
*/
|
|
6064
|
+
if (microAppWindow.document === oldMicroDocument && !false) {
|
|
6030
6065
|
iframeLocationReady();
|
|
6031
6066
|
}
|
|
6032
6067
|
else {
|
|
@@ -6123,7 +6158,7 @@ IframeSandbox.activeCount = 0; // number of active sandbox
|
|
|
6123
6158
|
// micro app instances
|
|
6124
6159
|
const appInstanceMap = new Map();
|
|
6125
6160
|
class CreateApp {
|
|
6126
|
-
constructor({ name, url, container, scopecss, useSandbox, inline, iframe, ssrUrl, isPrefetch, prefetchLevel, }) {
|
|
6161
|
+
constructor({ name, url, container, scopecss, useSandbox, inline, iframe, ssrUrl, isPrefetch, prefetchLevel, routerMode, }) {
|
|
6127
6162
|
this.state = appStates.CREATED;
|
|
6128
6163
|
this.keepAliveState = null;
|
|
6129
6164
|
this.loadSourceLevel = 0;
|
|
@@ -6133,7 +6168,6 @@ class CreateApp {
|
|
|
6133
6168
|
// TODO: 类型优化,加上iframe沙箱
|
|
6134
6169
|
this.sandBox = null;
|
|
6135
6170
|
this.fiber = false;
|
|
6136
|
-
this.routerMode = DEFAULT_ROUTER_MODE;
|
|
6137
6171
|
appInstanceMap.set(name, this);
|
|
6138
6172
|
// init actions
|
|
6139
6173
|
this.name = name;
|
|
@@ -6142,6 +6176,11 @@ class CreateApp {
|
|
|
6142
6176
|
this.scopecss = this.useSandbox && scopecss;
|
|
6143
6177
|
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
6144
6178
|
this.iframe = iframe !== null && iframe !== void 0 ? iframe : false;
|
|
6179
|
+
/**
|
|
6180
|
+
* NOTE:
|
|
6181
|
+
* 1. Navigate after micro-app created, before mount
|
|
6182
|
+
*/
|
|
6183
|
+
this.routerMode = routerMode || DEFAULT_ROUTER_MODE;
|
|
6145
6184
|
// not exist when prefetch 👇
|
|
6146
6185
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
6147
6186
|
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
@@ -6237,6 +6276,8 @@ class CreateApp {
|
|
|
6237
6276
|
return this.setAppState(appStates.LOADING);
|
|
6238
6277
|
}
|
|
6239
6278
|
this.createSandbox();
|
|
6279
|
+
// place outside of nextAction, as nextAction may execute async
|
|
6280
|
+
this.setAppState(appStates.BEFORE_MOUNT);
|
|
6240
6281
|
const nextAction = () => {
|
|
6241
6282
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
6242
6283
|
/**
|
|
@@ -6317,6 +6358,11 @@ class CreateApp {
|
|
|
6317
6358
|
this.handleMounted(this.umdHookMount(microApp.getData(this.name, true)));
|
|
6318
6359
|
}
|
|
6319
6360
|
catch (e) {
|
|
6361
|
+
/**
|
|
6362
|
+
* TODO:
|
|
6363
|
+
* 1. 是否应该直接抛出错误
|
|
6364
|
+
* 2. 是否应该触发error生命周期
|
|
6365
|
+
*/
|
|
6320
6366
|
logError('An error occurred in window.mount \n', this.name, e);
|
|
6321
6367
|
}
|
|
6322
6368
|
}
|
|
@@ -6350,7 +6396,10 @@ class CreateApp {
|
|
|
6350
6396
|
if (isPromise(umdHookMountResult)) {
|
|
6351
6397
|
umdHookMountResult
|
|
6352
6398
|
.then(() => this.dispatchMountedEvent())
|
|
6353
|
-
.catch(() =>
|
|
6399
|
+
.catch((e) => {
|
|
6400
|
+
logError('An error occurred in window.mount \n', this.name, e);
|
|
6401
|
+
this.dispatchMountedEvent();
|
|
6402
|
+
});
|
|
6354
6403
|
}
|
|
6355
6404
|
else {
|
|
6356
6405
|
this.dispatchMountedEvent();
|
|
@@ -6502,8 +6551,12 @@ class CreateApp {
|
|
|
6502
6551
|
var _a, _b;
|
|
6503
6552
|
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_HIDDEN);
|
|
6504
6553
|
/**
|
|
6505
|
-
*
|
|
6506
|
-
*
|
|
6554
|
+
* afterhidden事件需要提前发送,原因如下:
|
|
6555
|
+
* 1. 此时发送this.container还指向micro-app元素,而不是临时div元素
|
|
6556
|
+
* 2. 沙箱执行recordAndReleaseEffect后会将appstate-change方法也清空,之后再发送子应用也接受不到了
|
|
6557
|
+
* 3. 对于this.loadSourceLevel !== 2的情况,unmount是同步执行的,所以也会出现2的问题
|
|
6558
|
+
* TODO: 有可能导致的问题
|
|
6559
|
+
* 1. 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
|
|
6507
6560
|
*/
|
|
6508
6561
|
dispatchCustomEventToMicroApp(this, 'appstate-change', {
|
|
6509
6562
|
appState: 'afterhidden',
|
|
@@ -7345,8 +7398,6 @@ function defineElement(tagName) {
|
|
|
7345
7398
|
*/
|
|
7346
7399
|
this.handleAttributeUpdate = () => {
|
|
7347
7400
|
this.isWaiting = false;
|
|
7348
|
-
if (!this.connectStateMap.get(this.connectedCount))
|
|
7349
|
-
return;
|
|
7350
7401
|
const formatAttrName = formatAppName(this.getAttribute('name'));
|
|
7351
7402
|
const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
|
|
7352
7403
|
if (this.legalAttribute('name', formatAttrName) && this.legalAttribute('url', formatAttrUrl)) {
|
|
@@ -7456,7 +7507,9 @@ function defineElement(tagName) {
|
|
|
7456
7507
|
attributeChangedCallback(attr, _oldVal, newVal) {
|
|
7457
7508
|
if (this.legalAttribute(attr, newVal) &&
|
|
7458
7509
|
this[attr === ObservedAttrName.NAME ? 'appName' : 'appUrl'] !== newVal) {
|
|
7459
|
-
if (attr === ObservedAttrName.URL && !this.appUrl
|
|
7510
|
+
if (attr === ObservedAttrName.URL && (!this.appUrl ||
|
|
7511
|
+
!this.connectStateMap.get(this.connectedCount) // TODO: 这里的逻辑可否再优化一下
|
|
7512
|
+
)) {
|
|
7460
7513
|
newVal = formatAppURL(newVal, this.appName);
|
|
7461
7514
|
if (!newVal) {
|
|
7462
7515
|
return logError(`Invalid attribute url ${newVal}`, this.appName);
|
|
@@ -7464,11 +7517,14 @@ function defineElement(tagName) {
|
|
|
7464
7517
|
this.appUrl = newVal;
|
|
7465
7518
|
this.handleInitialNameAndUrl();
|
|
7466
7519
|
}
|
|
7467
|
-
else if (attr === ObservedAttrName.NAME && !this.appName
|
|
7520
|
+
else if (attr === ObservedAttrName.NAME && (!this.appName ||
|
|
7521
|
+
!this.connectStateMap.get(this.connectedCount) // TODO: 这里的逻辑可否再优化一下
|
|
7522
|
+
)) {
|
|
7468
7523
|
const formatNewName = formatAppName(newVal);
|
|
7469
7524
|
if (!formatNewName) {
|
|
7470
7525
|
return logError(`Invalid attribute name ${newVal}`, this.appName);
|
|
7471
7526
|
}
|
|
7527
|
+
// TODO: 当micro-app还未插入文档中就修改name,逻辑可否再优化一下
|
|
7472
7528
|
if (this.cacheData) {
|
|
7473
7529
|
microApp.setData(formatNewName, this.cacheData);
|
|
7474
7530
|
this.cacheData = null;
|
|
@@ -7615,6 +7671,7 @@ function defineElement(tagName) {
|
|
|
7615
7671
|
inline: this.getDisposeResult('inline'),
|
|
7616
7672
|
iframe: this.getDisposeResult('iframe'),
|
|
7617
7673
|
ssrUrl: this.ssrUrl,
|
|
7674
|
+
routerMode: this.getMemoryRouterMode(),
|
|
7618
7675
|
});
|
|
7619
7676
|
};
|
|
7620
7677
|
/**
|
|
@@ -7647,7 +7704,12 @@ function defineElement(tagName) {
|
|
|
7647
7704
|
*/
|
|
7648
7705
|
handleMount(app) {
|
|
7649
7706
|
app.isPrefetch = false;
|
|
7650
|
-
|
|
7707
|
+
/**
|
|
7708
|
+
* Fix error when navigate before app.mount by microApp.router.push(...)
|
|
7709
|
+
* Issue: https://github.com/micro-zoe/micro-app/issues/908
|
|
7710
|
+
*/
|
|
7711
|
+
app.setAppState(appStates.BEFORE_MOUNT);
|
|
7712
|
+
// exec mount async, simulate the first render scene
|
|
7651
7713
|
defer(() => this.mount(app));
|
|
7652
7714
|
}
|
|
7653
7715
|
/**
|
|
@@ -8186,6 +8248,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
8186
8248
|
constructor() {
|
|
8187
8249
|
super(...arguments);
|
|
8188
8250
|
this.tagName = 'micro-app';
|
|
8251
|
+
this.hasInit = false;
|
|
8189
8252
|
this.options = {};
|
|
8190
8253
|
this.router = router;
|
|
8191
8254
|
this.preFetch = preFetch;
|
|
@@ -8201,6 +8264,15 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
8201
8264
|
if (!isBrowser || !window.customElements) {
|
|
8202
8265
|
return logError('micro-app is not supported in this environment');
|
|
8203
8266
|
}
|
|
8267
|
+
/**
|
|
8268
|
+
* TODO: 优化代码和逻辑
|
|
8269
|
+
* 1、同一个基座中initGlobalEnv不能被多次执行,否则会导致死循环
|
|
8270
|
+
* 2、判断逻辑是否放在initGlobalEnv中合适?--- 不合适
|
|
8271
|
+
*/
|
|
8272
|
+
if (this.hasInit) {
|
|
8273
|
+
return logError('microApp.start executed repeatedly');
|
|
8274
|
+
}
|
|
8275
|
+
this.hasInit = true;
|
|
8204
8276
|
if (options === null || options === void 0 ? void 0 : options.tagName) {
|
|
8205
8277
|
if (/^micro-app(-\S+)?/.test(options.tagName)) {
|
|
8206
8278
|
this.tagName = options.tagName;
|