@micro-zoe/micro-app 1.0.0-beta.3 → 1.0.0-beta.4
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.esm.js +308 -165
- 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 +1 -0
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-beta.
|
|
1
|
+
const version = '1.0.0-beta.4';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -3705,31 +3705,41 @@ function patchWindowEffect(appName, microAppWindow) {
|
|
|
3705
3705
|
|
|
3706
3706
|
// set micro app state to origin state
|
|
3707
3707
|
function setMicroState(appName, microState) {
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3708
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3709
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
3710
|
+
const additionalState = {
|
|
3711
|
+
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
3712
|
+
[appName]: microState
|
|
3713
|
+
})
|
|
3714
|
+
};
|
|
3715
|
+
// create new state object
|
|
3716
|
+
return assign({}, rawState, additionalState);
|
|
3717
|
+
}
|
|
3718
|
+
return microState;
|
|
3716
3719
|
}
|
|
3717
3720
|
// delete micro app state form origin state
|
|
3718
3721
|
function removeMicroState(appName, rawState) {
|
|
3719
|
-
if (
|
|
3720
|
-
if (
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3722
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3723
|
+
if (isPlainObject(rawState === null || rawState === void 0 ? void 0 : rawState.microAppState)) {
|
|
3724
|
+
if (!isUndefined(rawState.microAppState[appName])) {
|
|
3725
|
+
delete rawState.microAppState[appName];
|
|
3726
|
+
}
|
|
3727
|
+
if (!Object.keys(rawState.microAppState).length) {
|
|
3728
|
+
delete rawState.microAppState;
|
|
3729
|
+
}
|
|
3725
3730
|
}
|
|
3731
|
+
return assign({}, rawState);
|
|
3726
3732
|
}
|
|
3727
|
-
return
|
|
3733
|
+
return rawState;
|
|
3728
3734
|
}
|
|
3729
3735
|
// get micro app state form origin state
|
|
3730
3736
|
function getMicroState(appName) {
|
|
3731
|
-
var _a
|
|
3732
|
-
|
|
3737
|
+
var _a;
|
|
3738
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
3739
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3740
|
+
return ((_a = rawState === null || rawState === void 0 ? void 0 : rawState.microAppState) === null || _a === void 0 ? void 0 : _a[appName]) || null;
|
|
3741
|
+
}
|
|
3742
|
+
return rawState;
|
|
3733
3743
|
}
|
|
3734
3744
|
const ENC_AD_RE = /&/g; // %M1
|
|
3735
3745
|
const ENC_EQ_RE = /=/g; // %M2
|
|
@@ -3767,53 +3777,61 @@ function formatQueryAppName(appName) {
|
|
|
3767
3777
|
function getMicroPathFromURL(appName) {
|
|
3768
3778
|
var _a, _b;
|
|
3769
3779
|
const rawLocation = globalEnv.rawWindow.location;
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3780
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3781
|
+
const queryObject = getQueryObjectFromURL(rawLocation.search, rawLocation.hash);
|
|
3782
|
+
const microPath = ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) || ((_b = queryObject.searchQuery) === null || _b === void 0 ? void 0 : _b[formatQueryAppName(appName)]);
|
|
3783
|
+
return isString(microPath) ? decodeMicroPath(microPath) : null;
|
|
3784
|
+
}
|
|
3785
|
+
return rawLocation.pathname + rawLocation.search + rawLocation.hash;
|
|
3773
3786
|
}
|
|
3774
3787
|
/**
|
|
3775
3788
|
* Attach child app fullPath to browser url
|
|
3776
3789
|
* @param appName app.name
|
|
3777
|
-
* @param
|
|
3790
|
+
* @param targetLocation location of child app or rawLocation of window
|
|
3778
3791
|
*/
|
|
3779
|
-
function setMicroPathToURL(appName,
|
|
3780
|
-
|
|
3781
|
-
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3782
|
-
const encodedMicroPath = encodeMicroPath(microLocation.pathname +
|
|
3783
|
-
microLocation.search +
|
|
3784
|
-
microLocation.hash);
|
|
3785
|
-
/**
|
|
3786
|
-
* Is parent is hash router
|
|
3787
|
-
* In fact, this is not true. It just means that the parameter is added to the hash
|
|
3788
|
-
*/
|
|
3792
|
+
function setMicroPathToURL(appName, targetLocation) {
|
|
3793
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3789
3794
|
let isAttach2Hash = false;
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3795
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3796
|
+
let { pathname, search, hash } = globalEnv.rawWindow.location;
|
|
3797
|
+
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3798
|
+
const encodedMicroPath = encodeMicroPath(targetFullPath);
|
|
3799
|
+
/**
|
|
3800
|
+
* Is parent is hash router
|
|
3801
|
+
* In fact, this is not true. It just means that the parameter is added to the hash
|
|
3802
|
+
*/
|
|
3803
|
+
// If hash exists and search does not exist, it is considered as a hash route
|
|
3804
|
+
if (hash && !search) {
|
|
3805
|
+
isAttach2Hash = true;
|
|
3806
|
+
if (queryObject.hashQuery) {
|
|
3807
|
+
queryObject.hashQuery[formatQueryAppName(appName)] = encodedMicroPath;
|
|
3808
|
+
}
|
|
3809
|
+
else {
|
|
3810
|
+
queryObject.hashQuery = {
|
|
3811
|
+
[formatQueryAppName(appName)]: encodedMicroPath
|
|
3812
|
+
};
|
|
3813
|
+
}
|
|
3814
|
+
const baseHash = hash.includes('?') ? hash.slice(0, hash.indexOf('?') + 1) : hash + '?';
|
|
3815
|
+
hash = baseHash + stringifyQuery(queryObject.hashQuery);
|
|
3807
3816
|
}
|
|
3808
3817
|
else {
|
|
3809
|
-
queryObject.searchQuery
|
|
3810
|
-
[formatQueryAppName(appName)]
|
|
3811
|
-
}
|
|
3818
|
+
if (queryObject.searchQuery) {
|
|
3819
|
+
queryObject.searchQuery[formatQueryAppName(appName)] = encodedMicroPath;
|
|
3820
|
+
}
|
|
3821
|
+
else {
|
|
3822
|
+
queryObject.searchQuery = {
|
|
3823
|
+
[formatQueryAppName(appName)]: encodedMicroPath
|
|
3824
|
+
};
|
|
3825
|
+
}
|
|
3826
|
+
search = '?' + stringifyQuery(queryObject.searchQuery);
|
|
3812
3827
|
}
|
|
3813
|
-
|
|
3828
|
+
return {
|
|
3829
|
+
fullPath: pathname + search + hash,
|
|
3830
|
+
isAttach2Hash,
|
|
3831
|
+
};
|
|
3814
3832
|
}
|
|
3815
3833
|
return {
|
|
3816
|
-
fullPath:
|
|
3834
|
+
fullPath: targetFullPath,
|
|
3817
3835
|
isAttach2Hash,
|
|
3818
3836
|
};
|
|
3819
3837
|
}
|
|
@@ -3825,18 +3843,20 @@ function setMicroPathToURL(appName, microLocation) {
|
|
|
3825
3843
|
function removeMicroPathFromURL(appName, targetLocation) {
|
|
3826
3844
|
var _a, _b, _c, _d;
|
|
3827
3845
|
let { pathname, search, hash } = targetLocation || globalEnv.rawWindow.location;
|
|
3828
|
-
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3829
3846
|
let isAttach2Hash = false;
|
|
3830
|
-
if ((
|
|
3831
|
-
|
|
3832
|
-
(
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3847
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
3848
|
+
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3849
|
+
if ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) {
|
|
3850
|
+
isAttach2Hash = true;
|
|
3851
|
+
(_b = queryObject.hashQuery) === null || _b === void 0 ? true : delete _b[formatQueryAppName(appName)];
|
|
3852
|
+
const hashQueryStr = stringifyQuery(queryObject.hashQuery);
|
|
3853
|
+
hash = hash.slice(0, hash.indexOf('?') + Number(Boolean(hashQueryStr))) + hashQueryStr;
|
|
3854
|
+
}
|
|
3855
|
+
else if ((_c = queryObject.searchQuery) === null || _c === void 0 ? void 0 : _c[formatQueryAppName(appName)]) {
|
|
3856
|
+
(_d = queryObject.searchQuery) === null || _d === void 0 ? true : delete _d[formatQueryAppName(appName)];
|
|
3857
|
+
const searchQueryStr = stringifyQuery(queryObject.searchQuery);
|
|
3858
|
+
search = searchQueryStr ? '?' + searchQueryStr : '';
|
|
3859
|
+
}
|
|
3840
3860
|
}
|
|
3841
3861
|
return {
|
|
3842
3862
|
fullPath: pathname + search + hash,
|
|
@@ -3876,7 +3896,23 @@ function getNoHashMicroPathFromURL(appName, baseUrl) {
|
|
|
3876
3896
|
*/
|
|
3877
3897
|
function isEffectiveApp(appName) {
|
|
3878
3898
|
const app = appInstanceMap.get(appName);
|
|
3879
|
-
|
|
3899
|
+
/**
|
|
3900
|
+
* !!(app && !app.isPrefetch && !app.isHidden())
|
|
3901
|
+
* 隐藏的keep-alive应用暂时不作为无效应用,原因如下
|
|
3902
|
+
* 1、隐藏后才执行去除浏览器上的微应用的路由信息的操作,导致微应用的路由信息无法去除
|
|
3903
|
+
* 2、如果保持隐藏应用内部正常跳转,阻止同步路由信息到浏览器,这样理论上是好的,但是对于location跳转改如何处理?location跳转是基于修改浏览器地址后发送popstate事件实现的,所以应该是在隐藏后不支持通过location进行跳转
|
|
3904
|
+
*/
|
|
3905
|
+
return !!(app && !app.isPrefetch);
|
|
3906
|
+
}
|
|
3907
|
+
/**
|
|
3908
|
+
* Determine whether the app has enabled memory-router
|
|
3909
|
+
* NOTE:
|
|
3910
|
+
* 1. if sandbox disabled, memory-router is disabled
|
|
3911
|
+
* 2. if app not exist, memory-router is disabled
|
|
3912
|
+
*/
|
|
3913
|
+
function isMemoryRouterEnabled(appName) {
|
|
3914
|
+
const app = appInstanceMap.get(appName);
|
|
3915
|
+
return !!(app && app.sandBox && app.useMemoryRouter);
|
|
3880
3916
|
}
|
|
3881
3917
|
|
|
3882
3918
|
/**
|
|
@@ -3899,26 +3935,7 @@ function addHistoryListener(appName) {
|
|
|
3899
3935
|
excludePreRender: true,
|
|
3900
3936
|
}).includes(appName) &&
|
|
3901
3937
|
!e.onlyForBrowser) {
|
|
3902
|
-
|
|
3903
|
-
const app = appInstanceMap.get(appName);
|
|
3904
|
-
const proxyWindow = app.sandBox.proxyWindow;
|
|
3905
|
-
const microAppWindow = app.sandBox.microAppWindow;
|
|
3906
|
-
let isHashChange = false;
|
|
3907
|
-
// for hashChangeEvent
|
|
3908
|
-
const oldHref = proxyWindow.location.href;
|
|
3909
|
-
// Do not attach micro state to url when microPath is empty
|
|
3910
|
-
if (microPath) {
|
|
3911
|
-
const oldHash = proxyWindow.location.hash;
|
|
3912
|
-
updateMicroLocation(appName, microPath, microAppWindow.location);
|
|
3913
|
-
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
3914
|
-
}
|
|
3915
|
-
// dispatch formatted popStateEvent to child
|
|
3916
|
-
dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow);
|
|
3917
|
-
// dispatch formatted hashChangeEvent to child when hash change
|
|
3918
|
-
if (isHashChange)
|
|
3919
|
-
dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref);
|
|
3920
|
-
// clear element scope before trigger event of next app
|
|
3921
|
-
removeDomScope();
|
|
3938
|
+
updateMicroLocationWithEvent(appName, getMicroPathFromURL(appName));
|
|
3922
3939
|
}
|
|
3923
3940
|
};
|
|
3924
3941
|
rawWindow.addEventListener('popstate', popStateHandler);
|
|
@@ -3926,6 +3943,35 @@ function addHistoryListener(appName) {
|
|
|
3926
3943
|
rawWindow.removeEventListener('popstate', popStateHandler);
|
|
3927
3944
|
};
|
|
3928
3945
|
}
|
|
3946
|
+
/**
|
|
3947
|
+
* Effect: use to trigger child app jump
|
|
3948
|
+
* Actions:
|
|
3949
|
+
* 1. update microLocation with target path
|
|
3950
|
+
* 2. dispatch popStateEvent & hashChangeEvent
|
|
3951
|
+
* @param appName app name
|
|
3952
|
+
* @param targetFullPath target path of child app
|
|
3953
|
+
*/
|
|
3954
|
+
function updateMicroLocationWithEvent(appName, targetFullPath) {
|
|
3955
|
+
const app = appInstanceMap.get(appName);
|
|
3956
|
+
const proxyWindow = app.sandBox.proxyWindow;
|
|
3957
|
+
const microAppWindow = app.sandBox.microAppWindow;
|
|
3958
|
+
let isHashChange = false;
|
|
3959
|
+
// for hashChangeEvent
|
|
3960
|
+
const oldHref = proxyWindow.location.href;
|
|
3961
|
+
// Do not attach micro state to url when targetFullPath is empty
|
|
3962
|
+
if (targetFullPath) {
|
|
3963
|
+
const oldHash = proxyWindow.location.hash;
|
|
3964
|
+
updateMicroLocation(appName, targetFullPath, microAppWindow.location);
|
|
3965
|
+
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
3966
|
+
}
|
|
3967
|
+
// dispatch formatted popStateEvent to child
|
|
3968
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow);
|
|
3969
|
+
// dispatch formatted hashChangeEvent to child when hash change
|
|
3970
|
+
if (isHashChange)
|
|
3971
|
+
dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref);
|
|
3972
|
+
// clear element scope before trigger event of next app
|
|
3973
|
+
removeDomScope();
|
|
3974
|
+
}
|
|
3929
3975
|
/**
|
|
3930
3976
|
* dispatch formatted popstate event to microApp
|
|
3931
3977
|
* @param appName app name
|
|
@@ -4088,6 +4134,8 @@ function nativeHistoryNavigate(appName, methodName, fullPath, state = null, titl
|
|
|
4088
4134
|
* 2. proxyHistory.pushState/replaceState with limited popstateEvent
|
|
4089
4135
|
* 3. api microApp.router.push/replace
|
|
4090
4136
|
* 4. proxyLocation.hash = xxx
|
|
4137
|
+
* NOTE:
|
|
4138
|
+
* 1. hidden keep-alive app can jump internally, but will not synchronize to browser
|
|
4091
4139
|
* @param appName app.name
|
|
4092
4140
|
* @param methodName pushState/replaceState
|
|
4093
4141
|
* @param result result of add/remove microApp path on browser url
|
|
@@ -4103,8 +4151,10 @@ function navigateWithNativeEvent(appName, methodName, result, onlyForBrowser, st
|
|
|
4103
4151
|
const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null;
|
|
4104
4152
|
// navigate with native history method
|
|
4105
4153
|
nativeHistoryNavigate(appName, methodName, result.fullPath, state, title);
|
|
4106
|
-
|
|
4154
|
+
// TODO: 如果所有模式统一发送popstate事件,则isMemoryRouterEnabled(appName)要去掉
|
|
4155
|
+
if (oldFullPath !== result.fullPath && isMemoryRouterEnabled(appName)) {
|
|
4107
4156
|
dispatchNativeEvent(appName, onlyForBrowser, oldHref);
|
|
4157
|
+
}
|
|
4108
4158
|
}
|
|
4109
4159
|
}
|
|
4110
4160
|
/**
|
|
@@ -4149,8 +4199,8 @@ function reWriteHistoryMethod(method) {
|
|
|
4149
4199
|
excludeHiddenApp: true,
|
|
4150
4200
|
excludePreRender: true,
|
|
4151
4201
|
}).forEach(appName => {
|
|
4152
|
-
|
|
4153
|
-
|
|
4202
|
+
if (isMemoryRouterEnabled(appName) && !getMicroPathFromURL(appName)) {
|
|
4203
|
+
const app = appInstanceMap.get(appName);
|
|
4154
4204
|
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
4155
4205
|
}
|
|
4156
4206
|
});
|
|
@@ -4199,12 +4249,14 @@ function createRouterApi() {
|
|
|
4199
4249
|
return function (to) {
|
|
4200
4250
|
const appName = formatAppName(to.name);
|
|
4201
4251
|
if (appName && isString(to.path)) {
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4252
|
+
/**
|
|
4253
|
+
* active apps, exclude prerender app or hidden keep-alive app
|
|
4254
|
+
* NOTE:
|
|
4255
|
+
* 1. prerender app or hidden keep-alive app clear and record popstate event, so we cannot control app jump through the API
|
|
4256
|
+
* 2. disable memory-router
|
|
4257
|
+
*/
|
|
4258
|
+
if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) {
|
|
4259
|
+
const app = appInstanceMap.get(appName);
|
|
4208
4260
|
const microLocation = app.sandBox.proxyWindow.location;
|
|
4209
4261
|
const targetLocation = createURL(to.path, microLocation.href);
|
|
4210
4262
|
// Only get path data, even if the origin is different from microApp
|
|
@@ -4213,20 +4265,48 @@ function createRouterApi() {
|
|
|
4213
4265
|
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
4214
4266
|
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
4215
4267
|
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
4268
|
+
/**
|
|
4269
|
+
* TODO:
|
|
4270
|
+
* 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明
|
|
4271
|
+
* 2. 关闭虚拟路由时跳转方式不同:1、基座跳转但不发送popstate事件 2、控制子应用更新location,内部发送popstate事件。
|
|
4272
|
+
* 补充:
|
|
4273
|
+
* 核心思路:减小对基座的影响(就是子应用跳转不向基座发送popstate事件,其他操作一致),但这是必要的吗,只是多了一个触发popstate的操作
|
|
4274
|
+
* 未来的思路有两种:
|
|
4275
|
+
* 1、减少对基座的影响,主要是解决vue循环刷新的问题
|
|
4276
|
+
* 2、全局发送popstate事件,解决主、子都是vue3的冲突问题
|
|
4277
|
+
* 两者选一个吧,如果选2,则下面这两行代码可以去掉
|
|
4278
|
+
* 要不这样吧,history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高
|
|
4279
|
+
* 如果关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。
|
|
4280
|
+
* 。。。。先这样吧
|
|
4281
|
+
*/
|
|
4282
|
+
if (!isMemoryRouterEnabled(appName)) {
|
|
4283
|
+
updateMicroLocationWithEvent(appName, targetFullPath);
|
|
4284
|
+
}
|
|
4216
4285
|
}
|
|
4217
4286
|
}
|
|
4218
4287
|
else {
|
|
4219
|
-
|
|
4220
|
-
* app not exit or unmounted, update browser URL with replaceState
|
|
4221
|
-
* use base app location.origin as baseURL
|
|
4222
|
-
*/
|
|
4223
|
-
const rawLocation = globalEnv.rawWindow.location;
|
|
4224
|
-
const targetLocation = createURL(to.path, rawLocation.origin);
|
|
4225
|
-
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
4226
|
-
if (getMicroPathFromURL(appName) !== targetFullPath) {
|
|
4227
|
-
navigateWithRawHistory(appName, to.replace === false ? 'pushState' : 'replaceState', targetLocation, to.state);
|
|
4228
|
-
}
|
|
4288
|
+
logWarn('navigation failed, app does not exist or is inactive');
|
|
4229
4289
|
}
|
|
4290
|
+
// /**
|
|
4291
|
+
// * app not exit or unmounted, update browser URL with replaceState
|
|
4292
|
+
// * use base app location.origin as baseURL
|
|
4293
|
+
// * 应用不存在或已卸载,依然使用replaceState来更新浏览器地址 -- 不合理
|
|
4294
|
+
// */
|
|
4295
|
+
// /**
|
|
4296
|
+
// * TODO: 应用还没渲染或已经卸载最好不要支持跳转了,我知道这是因为解决一些特殊场景,但这么做是非常反直觉的
|
|
4297
|
+
// * 并且在新版本中有多种路由模式,如果应用不存在,我们根本无法知道是哪种模式,那么这里的操作就无意义了。
|
|
4298
|
+
// */
|
|
4299
|
+
// const rawLocation = globalEnv.rawWindow.location
|
|
4300
|
+
// const targetLocation = createURL(to.path, rawLocation.origin)
|
|
4301
|
+
// const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash
|
|
4302
|
+
// if (getMicroPathFromURL(appName) !== targetFullPath) {
|
|
4303
|
+
// navigateWithRawHistory(
|
|
4304
|
+
// appName,
|
|
4305
|
+
// to.replace === false ? 'pushState' : 'replaceState',
|
|
4306
|
+
// targetLocation,
|
|
4307
|
+
// to.state,
|
|
4308
|
+
// )
|
|
4309
|
+
// }
|
|
4230
4310
|
}
|
|
4231
4311
|
else {
|
|
4232
4312
|
logError(`navigation failed, name & path are required when use router.${replace ? 'replace' : 'push'}`);
|
|
@@ -4286,8 +4366,8 @@ function createRouterApi() {
|
|
|
4286
4366
|
* 2. useMemoryRouter is false
|
|
4287
4367
|
*/
|
|
4288
4368
|
function commonHandlerForAttachToURL(appName) {
|
|
4289
|
-
|
|
4290
|
-
|
|
4369
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
4370
|
+
const app = appInstanceMap.get(appName);
|
|
4291
4371
|
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
4292
4372
|
}
|
|
4293
4373
|
}
|
|
@@ -4539,37 +4619,40 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4539
4619
|
// Even if the origin is the same, developers still have the possibility of want to jump to a new page
|
|
4540
4620
|
if (targetLocation.origin === proxyLocation.origin) {
|
|
4541
4621
|
const setMicroPathResult = setMicroPathToURL(appName, targetLocation);
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4622
|
+
// if disable memory-router, navigate directly through rawLocation
|
|
4623
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
4624
|
+
/**
|
|
4625
|
+
* change hash with location.href will not trigger the browser reload
|
|
4626
|
+
* so we use pushState & reload to imitate href behavior
|
|
4627
|
+
* NOTE:
|
|
4628
|
+
* 1. if child app only change hash, it should not trigger browser reload
|
|
4629
|
+
* 2. if address is same and has hash, it should not add route stack
|
|
4630
|
+
*/
|
|
4631
|
+
if (targetLocation.pathname === proxyLocation.pathname &&
|
|
4632
|
+
targetLocation.search === proxyLocation.search) {
|
|
4633
|
+
let oldHref = null;
|
|
4634
|
+
if (targetLocation.hash !== proxyLocation.hash) {
|
|
4635
|
+
if (setMicroPathResult.isAttach2Hash)
|
|
4636
|
+
oldHref = rawLocation.href;
|
|
4637
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4638
|
+
}
|
|
4639
|
+
if (targetLocation.hash) {
|
|
4640
|
+
dispatchNativeEvent(appName, false, oldHref);
|
|
4641
|
+
}
|
|
4642
|
+
else {
|
|
4643
|
+
reload();
|
|
4644
|
+
}
|
|
4645
|
+
return void 0;
|
|
4646
|
+
/**
|
|
4647
|
+
* when baseApp is hash router, address change of child can not reload browser
|
|
4648
|
+
* so we imitate behavior of browser (reload) manually
|
|
4649
|
+
*/
|
|
4559
4650
|
}
|
|
4560
|
-
else {
|
|
4651
|
+
else if (setMicroPathResult.isAttach2Hash) {
|
|
4652
|
+
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4561
4653
|
reload();
|
|
4654
|
+
return void 0;
|
|
4562
4655
|
}
|
|
4563
|
-
return void 0;
|
|
4564
|
-
/**
|
|
4565
|
-
* when baseApp is hash router, address change of child can not reload browser
|
|
4566
|
-
* so we imitate behavior of browser (reload) manually
|
|
4567
|
-
*/
|
|
4568
|
-
}
|
|
4569
|
-
else if (setMicroPathResult.isAttach2Hash) {
|
|
4570
|
-
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4571
|
-
reload();
|
|
4572
|
-
return void 0;
|
|
4573
4656
|
}
|
|
4574
4657
|
return setMicroPathResult.fullPath;
|
|
4575
4658
|
}
|
|
@@ -4661,19 +4744,34 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4661
4744
|
}
|
|
4662
4745
|
}
|
|
4663
4746
|
else if (key === 'pathname') {
|
|
4664
|
-
|
|
4665
|
-
|
|
4747
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
4748
|
+
const targetPath = ('/' + value).replace(/^\/+/, '/') + proxyLocation.search + proxyLocation.hash;
|
|
4749
|
+
handleForPathNameAndSearch(targetPath, 'pathname');
|
|
4750
|
+
}
|
|
4751
|
+
else {
|
|
4752
|
+
rawLocation.pathname = value;
|
|
4753
|
+
}
|
|
4666
4754
|
}
|
|
4667
4755
|
else if (key === 'search') {
|
|
4668
|
-
|
|
4669
|
-
|
|
4756
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
4757
|
+
const targetPath = proxyLocation.pathname + ('?' + value).replace(/^\?+/, '?') + proxyLocation.hash;
|
|
4758
|
+
handleForPathNameAndSearch(targetPath, 'search');
|
|
4759
|
+
}
|
|
4760
|
+
else {
|
|
4761
|
+
rawLocation.search = value;
|
|
4762
|
+
}
|
|
4670
4763
|
}
|
|
4671
4764
|
else if (key === 'hash') {
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4765
|
+
if (isMemoryRouterEnabled(appName)) {
|
|
4766
|
+
const targetPath = proxyLocation.pathname + proxyLocation.search + ('#' + value).replace(/^#+/, '#');
|
|
4767
|
+
const targetLocation = createURL(targetPath, url);
|
|
4768
|
+
// The same hash will not trigger popStateEvent
|
|
4769
|
+
if (targetLocation.hash !== proxyLocation.hash) {
|
|
4770
|
+
navigateWithNativeEvent(appName, 'pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
else {
|
|
4774
|
+
rawLocation.hash = value;
|
|
4677
4775
|
}
|
|
4678
4776
|
}
|
|
4679
4777
|
else {
|
|
@@ -4718,6 +4816,7 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
4718
4816
|
var _a;
|
|
4719
4817
|
// record old values of microLocation to `from`
|
|
4720
4818
|
const from = createGuardLocation(appName, microLocation);
|
|
4819
|
+
// if is iframeSandbox, microLocation muse be rawLocation of iframe, not proxyLocation
|
|
4721
4820
|
const newLocation = createURL(path, microLocation.href);
|
|
4722
4821
|
if (isIframeSandbox(appName)) {
|
|
4723
4822
|
const microAppWindow = appInstanceMap.get(appName).sandBox.microAppWindow;
|
|
@@ -4736,6 +4835,15 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
4736
4835
|
}
|
|
4737
4836
|
}
|
|
4738
4837
|
|
|
4838
|
+
/**
|
|
4839
|
+
* TODO: 关于关闭虚拟路由系统的临时笔记
|
|
4840
|
+
* 1. with沙箱关闭虚拟路由最好和iframe保持一致
|
|
4841
|
+
* 2. default-page无法使用,但是用基座的地址可以实现一样的效果
|
|
4842
|
+
* 3. keep-router-state功能失效,因为始终为true
|
|
4843
|
+
* 4. 基座控制子应用跳转地址改变,正确的值为:baseRoute + 子应用地址,这要在文档中说明,否则很容易出错,确实也很难理解
|
|
4844
|
+
* 5. 是否需要发送popstate事件,为了减小对基座的影响,现在不发送
|
|
4845
|
+
* 6. 关闭后导致的vue3路由冲突问题需要在文档中明确指出(2处:在关闭虚拟路由系统的配置那里着重说明,在vue常见问题中说明)
|
|
4846
|
+
*/
|
|
4739
4847
|
/**
|
|
4740
4848
|
* The router system has two operations: read and write
|
|
4741
4849
|
* Read through location and write through history & location
|
|
@@ -4767,7 +4875,9 @@ function initRouteStateWithURL(appName, microLocation, defaultPage) {
|
|
|
4767
4875
|
}
|
|
4768
4876
|
/**
|
|
4769
4877
|
* initialize browser information according to microLocation
|
|
4770
|
-
*
|
|
4878
|
+
* Scenes:
|
|
4879
|
+
* 1. sandbox.start
|
|
4880
|
+
* 2. reshow of keep-alive app
|
|
4771
4881
|
*/
|
|
4772
4882
|
function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
4773
4883
|
// update microLocation with defaultPage
|
|
@@ -4790,14 +4900,14 @@ function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
|
4790
4900
|
const { pathname, search, hash } = createURL(url);
|
|
4791
4901
|
updateMicroLocation(appName, pathname + search + hash, microLocation, 'prevent');
|
|
4792
4902
|
}
|
|
4793
|
-
|
|
4903
|
+
removePathFromBrowser(appName);
|
|
4794
4904
|
clearRouterWhenUnmount(appName);
|
|
4795
4905
|
}
|
|
4796
4906
|
/**
|
|
4797
4907
|
* remove microState from history.state and remove microPath from browserURL
|
|
4798
4908
|
* called on sandbox.stop or hidden of keep-alive app
|
|
4799
4909
|
*/
|
|
4800
|
-
function
|
|
4910
|
+
function removePathFromBrowser(appName) {
|
|
4801
4911
|
attachRouteToBrowserURL(appName, removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
4802
4912
|
}
|
|
4803
4913
|
|
|
@@ -4941,6 +5051,7 @@ class WithSandBox {
|
|
|
4941
5051
|
if (this.active)
|
|
4942
5052
|
return;
|
|
4943
5053
|
this.active = true;
|
|
5054
|
+
// TODO: with沙箱关闭虚拟路由保持和iframe一致
|
|
4944
5055
|
if (useMemoryRouter) {
|
|
4945
5056
|
if (isUndefined(this.microAppWindow.location)) {
|
|
4946
5057
|
this.setMicroAppRouter(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, this.microAppWindow);
|
|
@@ -4977,16 +5088,18 @@ class WithSandBox {
|
|
|
4977
5088
|
* @param keepRouteState prevent reset route
|
|
4978
5089
|
* @param destroy completely destroy, delete cache resources
|
|
4979
5090
|
* @param clearData clear data from base app
|
|
5091
|
+
* @param useMemoryRouter use virtual router
|
|
4980
5092
|
*/
|
|
4981
|
-
stop({ umdMode, keepRouteState, destroy, clearData, }) {
|
|
5093
|
+
stop({ umdMode, keepRouteState, destroy, clearData, useMemoryRouter, }) {
|
|
5094
|
+
var _a;
|
|
4982
5095
|
if (!this.active)
|
|
4983
5096
|
return;
|
|
4984
5097
|
this.recordAndReleaseEffect({ umdMode, clearData, destroy }, !umdMode || destroy);
|
|
4985
|
-
if (
|
|
5098
|
+
if (useMemoryRouter) {
|
|
4986
5099
|
this.clearRouteState(keepRouteState);
|
|
4987
|
-
// release listener of popstate
|
|
4988
|
-
this.removeHistoryListener();
|
|
4989
5100
|
}
|
|
5101
|
+
// release listener of popstate for child app
|
|
5102
|
+
(_a = this.removeHistoryListener) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
4990
5103
|
/**
|
|
4991
5104
|
* NOTE:
|
|
4992
5105
|
* 1. injectedKeys and escapeKeys must be placed at the back
|
|
@@ -5428,7 +5541,7 @@ class WithSandBox {
|
|
|
5428
5541
|
updateBrowserURLWithLocation(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location);
|
|
5429
5542
|
}
|
|
5430
5543
|
removeRouteInfoForKeepAliveApp() {
|
|
5431
|
-
|
|
5544
|
+
removePathFromBrowser(this.microAppWindow.__MICRO_APP_NAME__);
|
|
5432
5545
|
}
|
|
5433
5546
|
/**
|
|
5434
5547
|
* Format all html elements when init
|
|
@@ -6206,12 +6319,29 @@ class IframeSandbox {
|
|
|
6206
6319
|
if (this.active)
|
|
6207
6320
|
return;
|
|
6208
6321
|
this.active = true;
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6322
|
+
/**
|
|
6323
|
+
* Sync router info to iframe when exec sandbox.start with disable or enable memory-router
|
|
6324
|
+
* e.g.:
|
|
6325
|
+
* vue-router@4.x get target path by remove the base section from rawLocation.pathname
|
|
6326
|
+
* code: window.location.pathname.slice(base.length) || '/'; (base is baseroute)
|
|
6327
|
+
* NOTE:
|
|
6328
|
+
* 1. iframe router and browser router are separated, we should update iframe router manually
|
|
6329
|
+
* 2. withSandbox location is browser location when disable memory-router, so no need to do anything
|
|
6330
|
+
*/
|
|
6331
|
+
/**
|
|
6332
|
+
* TODO:
|
|
6333
|
+
* 做一些记录:
|
|
6334
|
+
* 1. iframe关闭虚拟路由系统后,default-page无法使用,推荐用户直接使用浏览器地址控制首页渲染
|
|
6335
|
+
* 补充:keep-router-state 也无法配置,因为keep-router-state一定为true。
|
|
6336
|
+
* 2. 导航拦截、current.route 可以正常使用
|
|
6337
|
+
* 3. 可以正常控制子应用跳转,方式还是自上而下(也可以是子应用内部跳转,这种方式更好一点,减小对基座的影响,不会导致vue的循环刷新)
|
|
6338
|
+
* 4. 关闭虚拟路由以后会对应 route-mode='custom' 模式,包括with沙箱也会这么做
|
|
6339
|
+
* 5. 关闭虚拟路由是指尽可能模式没有虚拟路由的情况,子应用直接获取浏览器location和history,控制浏览器跳转
|
|
6340
|
+
*/
|
|
6341
|
+
this.initRouteState(defaultPage);
|
|
6342
|
+
// unique listener of popstate event for child app
|
|
6343
|
+
this.removeHistoryListener = addHistoryListener(this.microAppWindow.__MICRO_APP_NAME__);
|
|
6344
|
+
if (!useMemoryRouter) {
|
|
6215
6345
|
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
6216
6346
|
}
|
|
6217
6347
|
/**
|
|
@@ -6227,15 +6357,15 @@ class IframeSandbox {
|
|
|
6227
6357
|
}
|
|
6228
6358
|
if (++IframeSandbox.activeCount === 1) ;
|
|
6229
6359
|
}
|
|
6230
|
-
stop({ umdMode, keepRouteState, destroy, clearData, }) {
|
|
6360
|
+
stop({ umdMode, keepRouteState, destroy, clearData, useMemoryRouter, }) {
|
|
6361
|
+
var _a;
|
|
6231
6362
|
if (!this.active)
|
|
6232
6363
|
return;
|
|
6233
6364
|
this.recordAndReleaseEffect({ clearData }, !umdMode || destroy);
|
|
6234
|
-
if
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
}
|
|
6365
|
+
// if keep-route-state is true or disable memory-router, preserve microLocation state
|
|
6366
|
+
this.clearRouteState(keepRouteState || !useMemoryRouter);
|
|
6367
|
+
// release listener of popstate for child app
|
|
6368
|
+
(_a = this.removeHistoryListener) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
6239
6369
|
if (!umdMode || destroy) {
|
|
6240
6370
|
this.deleteIframeElement();
|
|
6241
6371
|
this.escapeKeys.forEach((key) => {
|
|
@@ -6478,7 +6608,7 @@ class IframeSandbox {
|
|
|
6478
6608
|
updateBrowserURLWithLocation(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location);
|
|
6479
6609
|
}
|
|
6480
6610
|
removeRouteInfoForKeepAliveApp() {
|
|
6481
|
-
|
|
6611
|
+
removePathFromBrowser(this.microAppWindow.__MICRO_APP_NAME__);
|
|
6482
6612
|
}
|
|
6483
6613
|
/**
|
|
6484
6614
|
* Format all html elements when init
|
|
@@ -6832,6 +6962,12 @@ class CreateApp {
|
|
|
6832
6962
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordAndReleaseEffect({ keepAlive: true });
|
|
6833
6963
|
}
|
|
6834
6964
|
}
|
|
6965
|
+
/**
|
|
6966
|
+
* TODO: 这里增加一个处理,如果渲染完成时已经卸载,则进行一些操作
|
|
6967
|
+
* 如果是默认模式:删除所有事件和定时器
|
|
6968
|
+
* 如果是umd模式:重新记录和清空事件
|
|
6969
|
+
* 补充:非必需,优先级低
|
|
6970
|
+
*/
|
|
6835
6971
|
}
|
|
6836
6972
|
/**
|
|
6837
6973
|
* unmount app
|
|
@@ -6913,6 +7049,7 @@ class CreateApp {
|
|
|
6913
7049
|
keepRouteState: keepRouteState && !destroy,
|
|
6914
7050
|
destroy,
|
|
6915
7051
|
clearData: clearData || destroy,
|
|
7052
|
+
useMemoryRouter: this.useMemoryRouter,
|
|
6916
7053
|
});
|
|
6917
7054
|
// dispatch unmount event to base app
|
|
6918
7055
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
@@ -6971,6 +7108,12 @@ class CreateApp {
|
|
|
6971
7108
|
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
6972
7109
|
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_SHOW);
|
|
6973
7110
|
this.container = cloneContainer(container, this.container, false);
|
|
7111
|
+
/**
|
|
7112
|
+
* TODO:
|
|
7113
|
+
* 1. iframe沙箱在关闭虚拟路由系统时,重新展示时不更新浏览器地址,这样和with沙箱保持一致。
|
|
7114
|
+
* 但是iframe是可以做到重新展示时更新浏览器地址的,这里临时不支持,等待后续with沙箱也支持的时候再优化
|
|
7115
|
+
* 只需要去除 if (this.useMemoryRouter) 的判断即可
|
|
7116
|
+
*/
|
|
6974
7117
|
if (this.useMemoryRouter) {
|
|
6975
7118
|
// called before lifeCyclesEvent
|
|
6976
7119
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
|