@micro-zoe/micro-app 0.5.3 → 0.6.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 +6 -2
- package/lib/index.esm.js +210 -93
- 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 +4 -4
- package/polyfill/jsx-custom-event.js +11 -1
- package/polyfill/jsx-custom-event.js.map +1 -1
- package/typings/global.d.ts +12 -4
package/lib/index.d.ts
CHANGED
|
@@ -324,15 +324,19 @@ declare module '@micro-zoe/micro-app/create_app' {
|
|
|
324
324
|
/**
|
|
325
325
|
* unmount app
|
|
326
326
|
* @param destroy completely destroy, delete cache resources
|
|
327
|
+
* @param unmountcb callback of unmount
|
|
327
328
|
*/
|
|
328
|
-
unmount(destroy: boolean): void;
|
|
329
|
+
unmount(destroy: boolean, unmountcb?: CallableFunction): void;
|
|
329
330
|
actionsForCompletelyDestory(): void;
|
|
331
|
+
hiddenKeepAliveApp(): void;
|
|
332
|
+
showKeepAliveApp(container: HTMLElement | ShadowRoot): void;
|
|
330
333
|
/**
|
|
331
334
|
* app rendering error
|
|
332
335
|
* @param e Error
|
|
333
336
|
*/
|
|
334
337
|
onerror(e: Error): void;
|
|
335
|
-
|
|
338
|
+
getAppState(): string;
|
|
339
|
+
getKeepAliveState(): string | null;
|
|
336
340
|
}
|
|
337
341
|
export function getActiveApps(): string[];
|
|
338
342
|
export function getAllApps(): string[];
|
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.
|
|
1
|
+
const version = '0.6.0';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -297,16 +297,16 @@ var ObservedAttrName;
|
|
|
297
297
|
ObservedAttrName["URL"] = "url";
|
|
298
298
|
})(ObservedAttrName || (ObservedAttrName = {}));
|
|
299
299
|
// app status
|
|
300
|
-
var
|
|
301
|
-
(function (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
})(
|
|
300
|
+
var appStates;
|
|
301
|
+
(function (appStates) {
|
|
302
|
+
appStates["NOT_LOADED"] = "NOT_LOADED";
|
|
303
|
+
appStates["LOADING_SOURCE_CODE"] = "LOADING_SOURCE_CODE";
|
|
304
|
+
appStates["LOAD_SOURCE_FINISHED"] = "LOAD_SOURCE_FINISHED";
|
|
305
|
+
appStates["LOAD_SOURCE_ERROR"] = "LOAD_SOURCE_ERROR";
|
|
306
|
+
appStates["MOUNTING"] = "MOUNTING";
|
|
307
|
+
appStates["MOUNTED"] = "MOUNTED";
|
|
308
|
+
appStates["UNMOUNT"] = "UNMOUNT";
|
|
309
|
+
})(appStates || (appStates = {}));
|
|
310
310
|
// lifecycles
|
|
311
311
|
var lifeCycles;
|
|
312
312
|
(function (lifeCycles) {
|
|
@@ -315,7 +315,17 @@ var lifeCycles;
|
|
|
315
315
|
lifeCycles["MOUNTED"] = "mounted";
|
|
316
316
|
lifeCycles["UNMOUNT"] = "unmount";
|
|
317
317
|
lifeCycles["ERROR"] = "error";
|
|
318
|
+
// 👇 keep-alive only
|
|
319
|
+
lifeCycles["BEFORESHOW"] = "beforeshow";
|
|
320
|
+
lifeCycles["AFTERSHOW"] = "aftershow";
|
|
321
|
+
lifeCycles["AFTERHIDDEN"] = "afterhidden";
|
|
318
322
|
})(lifeCycles || (lifeCycles = {}));
|
|
323
|
+
// keep-alive status
|
|
324
|
+
var keepAliveStates;
|
|
325
|
+
(function (keepAliveStates) {
|
|
326
|
+
keepAliveStates["KEEP_ALIVE_SHOW"] = "KEEP_ALIVE_SHOW";
|
|
327
|
+
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "KEEP_ALIVE_HIDDEN";
|
|
328
|
+
})(keepAliveStates || (keepAliveStates = {}));
|
|
319
329
|
|
|
320
330
|
/**
|
|
321
331
|
* fetch source of html, js, css
|
|
@@ -1317,14 +1327,16 @@ function releaseEffectDocumentEvent() {
|
|
|
1317
1327
|
document.addEventListener = globalEnv.rawDocumentAddEventListener;
|
|
1318
1328
|
document.removeEventListener = globalEnv.rawDocumentRemoveEventListener;
|
|
1319
1329
|
}
|
|
1330
|
+
// this events should be sent to the specified app
|
|
1331
|
+
const formatEventList = ['unmount', 'appstate-change'];
|
|
1320
1332
|
/**
|
|
1321
1333
|
* Format event name
|
|
1322
1334
|
* @param type event name
|
|
1323
1335
|
* @param microWindow micro window
|
|
1324
1336
|
*/
|
|
1325
1337
|
function formatEventType(type, microWindow) {
|
|
1326
|
-
if (type
|
|
1327
|
-
return
|
|
1338
|
+
if (formatEventList.includes(type)) {
|
|
1339
|
+
return `${type}-${microWindow.__MICRO_APP_NAME__}`;
|
|
1328
1340
|
}
|
|
1329
1341
|
return type;
|
|
1330
1342
|
}
|
|
@@ -2076,11 +2088,15 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
2076
2088
|
element.dispatchEvent(event);
|
|
2077
2089
|
}
|
|
2078
2090
|
/**
|
|
2079
|
-
* Dispatch
|
|
2080
|
-
* @param
|
|
2091
|
+
* Dispatch custom event to micro app
|
|
2092
|
+
* @param eventName event name
|
|
2093
|
+
* @param appName app name
|
|
2094
|
+
* @param detail event detail
|
|
2081
2095
|
*/
|
|
2082
|
-
function
|
|
2083
|
-
const event = new CustomEvent(
|
|
2096
|
+
function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
2097
|
+
const event = new CustomEvent(`${eventName}-${appName}`, {
|
|
2098
|
+
detail,
|
|
2099
|
+
});
|
|
2084
2100
|
window.dispatchEvent(event);
|
|
2085
2101
|
}
|
|
2086
2102
|
|
|
@@ -2088,7 +2104,9 @@ function dispatchUnmountToMicroApp(appName) {
|
|
|
2088
2104
|
const appInstanceMap = new Map();
|
|
2089
2105
|
class CreateApp {
|
|
2090
2106
|
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, macro, baseroute, }) {
|
|
2091
|
-
this.
|
|
2107
|
+
this.state = appStates.NOT_LOADED;
|
|
2108
|
+
this.keepAliveState = null;
|
|
2109
|
+
this.keepAliveContainer = null;
|
|
2092
2110
|
this.loadSourceLevel = 0;
|
|
2093
2111
|
this.umdHookMount = null;
|
|
2094
2112
|
this.umdHookUnmount = null;
|
|
@@ -2118,7 +2136,7 @@ class CreateApp {
|
|
|
2118
2136
|
}
|
|
2119
2137
|
// Load resources
|
|
2120
2138
|
loadSourceCode() {
|
|
2121
|
-
this.
|
|
2139
|
+
this.state = appStates.LOADING_SOURCE_CODE;
|
|
2122
2140
|
extractHtml(this);
|
|
2123
2141
|
}
|
|
2124
2142
|
/**
|
|
@@ -2127,9 +2145,9 @@ class CreateApp {
|
|
|
2127
2145
|
onLoad(html) {
|
|
2128
2146
|
if (++this.loadSourceLevel === 2) {
|
|
2129
2147
|
this.source.html = html;
|
|
2130
|
-
if (this.isPrefetch ||
|
|
2148
|
+
if (this.isPrefetch || appStates.UNMOUNT === this.state)
|
|
2131
2149
|
return;
|
|
2132
|
-
this.
|
|
2150
|
+
this.state = appStates.LOAD_SOURCE_FINISHED;
|
|
2133
2151
|
this.mount();
|
|
2134
2152
|
}
|
|
2135
2153
|
}
|
|
@@ -2139,9 +2157,9 @@ class CreateApp {
|
|
|
2139
2157
|
*/
|
|
2140
2158
|
onLoadError(e) {
|
|
2141
2159
|
this.loadSourceLevel = -1;
|
|
2142
|
-
if (
|
|
2160
|
+
if (appStates.UNMOUNT !== this.state) {
|
|
2143
2161
|
this.onerror(e);
|
|
2144
|
-
this.
|
|
2162
|
+
this.state = appStates.LOAD_SOURCE_ERROR;
|
|
2145
2163
|
}
|
|
2146
2164
|
}
|
|
2147
2165
|
/**
|
|
@@ -2158,11 +2176,11 @@ class CreateApp {
|
|
|
2158
2176
|
this.container = (_a = this.container) !== null && _a !== void 0 ? _a : container;
|
|
2159
2177
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : this.baseroute;
|
|
2160
2178
|
if (this.loadSourceLevel !== 2) {
|
|
2161
|
-
this.
|
|
2179
|
+
this.state = appStates.LOADING_SOURCE_CODE;
|
|
2162
2180
|
return;
|
|
2163
2181
|
}
|
|
2164
2182
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
2165
|
-
this.
|
|
2183
|
+
this.state = appStates.MOUNTING;
|
|
2166
2184
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
2167
2185
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute);
|
|
2168
2186
|
let umdHookMountResult; // result of mount function
|
|
@@ -2222,20 +2240,23 @@ class CreateApp {
|
|
|
2222
2240
|
* dispatch mounted event when app run finished
|
|
2223
2241
|
*/
|
|
2224
2242
|
dispatchMountedEvent() {
|
|
2225
|
-
if (
|
|
2226
|
-
this.
|
|
2243
|
+
if (appStates.UNMOUNT !== this.state) {
|
|
2244
|
+
this.state = appStates.MOUNTED;
|
|
2227
2245
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.MOUNTED);
|
|
2228
2246
|
}
|
|
2229
2247
|
}
|
|
2230
2248
|
/**
|
|
2231
2249
|
* unmount app
|
|
2232
2250
|
* @param destroy completely destroy, delete cache resources
|
|
2251
|
+
* @param unmountcb callback of unmount
|
|
2233
2252
|
*/
|
|
2234
|
-
unmount(destroy) {
|
|
2235
|
-
if (this.
|
|
2253
|
+
unmount(destroy, unmountcb) {
|
|
2254
|
+
if (this.state === appStates.LOAD_SOURCE_ERROR) {
|
|
2236
2255
|
destroy = true;
|
|
2237
2256
|
}
|
|
2238
|
-
this.
|
|
2257
|
+
this.state = appStates.UNMOUNT;
|
|
2258
|
+
this.keepAliveState = null;
|
|
2259
|
+
this.keepAliveContainer = null;
|
|
2239
2260
|
// result of unmount function
|
|
2240
2261
|
let umdHookUnmountResult;
|
|
2241
2262
|
/**
|
|
@@ -2251,28 +2272,31 @@ class CreateApp {
|
|
|
2251
2272
|
}
|
|
2252
2273
|
}
|
|
2253
2274
|
// dispatch unmount event to micro app
|
|
2254
|
-
|
|
2255
|
-
this.handleUnmounted(destroy, umdHookUnmountResult);
|
|
2275
|
+
dispatchCustomEventToMicroApp('unmount', this.name);
|
|
2276
|
+
this.handleUnmounted(destroy, umdHookUnmountResult, unmountcb);
|
|
2256
2277
|
}
|
|
2257
2278
|
/**
|
|
2258
2279
|
* handle for promise umdHookUnmount
|
|
2280
|
+
* @param destroy completely destroy, delete cache resources
|
|
2259
2281
|
* @param umdHookUnmountResult result of umdHookUnmount
|
|
2282
|
+
* @param unmountcb callback of unmount
|
|
2260
2283
|
*/
|
|
2261
|
-
handleUnmounted(destroy, umdHookUnmountResult) {
|
|
2284
|
+
handleUnmounted(destroy, umdHookUnmountResult, unmountcb) {
|
|
2262
2285
|
if (isPromise(umdHookUnmountResult)) {
|
|
2263
2286
|
umdHookUnmountResult
|
|
2264
|
-
.then(() => this.actionsForUnmount(destroy))
|
|
2265
|
-
.catch(() => this.actionsForUnmount(destroy));
|
|
2287
|
+
.then(() => this.actionsForUnmount(destroy, unmountcb))
|
|
2288
|
+
.catch(() => this.actionsForUnmount(destroy, unmountcb));
|
|
2266
2289
|
}
|
|
2267
2290
|
else {
|
|
2268
|
-
this.actionsForUnmount(destroy);
|
|
2291
|
+
this.actionsForUnmount(destroy, unmountcb);
|
|
2269
2292
|
}
|
|
2270
2293
|
}
|
|
2271
2294
|
/**
|
|
2272
2295
|
* actions for unmount app
|
|
2273
2296
|
* @param destroy completely destroy, delete cache resources
|
|
2297
|
+
* @param unmountcb callback of unmount
|
|
2274
2298
|
*/
|
|
2275
|
-
actionsForUnmount(destroy) {
|
|
2299
|
+
actionsForUnmount(destroy, unmountcb) {
|
|
2276
2300
|
var _a;
|
|
2277
2301
|
// dispatch unmount event to base app
|
|
2278
2302
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
@@ -2281,12 +2305,11 @@ class CreateApp {
|
|
|
2281
2305
|
this.actionsForCompletelyDestory();
|
|
2282
2306
|
}
|
|
2283
2307
|
else if (this.umdMode && this.container.childElementCount) {
|
|
2284
|
-
/**
|
|
2285
|
-
* In umd mode, ui frameworks will no longer create style elements to head in lazy load page when render again, so we should save container to keep these elements
|
|
2286
|
-
*/
|
|
2287
2308
|
cloneContainer(this.container, this.source.html, false);
|
|
2288
2309
|
}
|
|
2310
|
+
this.container.innerHTML = '';
|
|
2289
2311
|
this.container = null;
|
|
2312
|
+
unmountcb && unmountcb();
|
|
2290
2313
|
}
|
|
2291
2314
|
// actions for completely destroy
|
|
2292
2315
|
actionsForCompletelyDestory() {
|
|
@@ -2295,6 +2318,37 @@ class CreateApp {
|
|
|
2295
2318
|
}
|
|
2296
2319
|
appInstanceMap.delete(this.name);
|
|
2297
2320
|
}
|
|
2321
|
+
// hidden app when disconnectedCallback called with keep-alive
|
|
2322
|
+
hiddenKeepAliveApp() {
|
|
2323
|
+
this.keepAliveState = keepAliveStates.KEEP_ALIVE_HIDDEN;
|
|
2324
|
+
// event should dispatch before clone node
|
|
2325
|
+
// dispatch afterhidden event to micro-app
|
|
2326
|
+
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
2327
|
+
appState: 'afterhidden',
|
|
2328
|
+
});
|
|
2329
|
+
// dispatch afterhidden event to base app
|
|
2330
|
+
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERHIDDEN);
|
|
2331
|
+
cloneContainer(this.container, this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')), false);
|
|
2332
|
+
this.container = this.keepAliveContainer;
|
|
2333
|
+
}
|
|
2334
|
+
// show app when connectedCallback called with keep-alive
|
|
2335
|
+
showKeepAliveApp(container) {
|
|
2336
|
+
// dispatch beforeshow event to micro-app
|
|
2337
|
+
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
2338
|
+
appState: 'beforeshow',
|
|
2339
|
+
});
|
|
2340
|
+
// dispatch beforeshow event to base app
|
|
2341
|
+
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
2342
|
+
cloneContainer(this.container, container, false);
|
|
2343
|
+
this.container = container;
|
|
2344
|
+
this.keepAliveState = keepAliveStates.KEEP_ALIVE_SHOW;
|
|
2345
|
+
// dispatch aftershow event to micro-app
|
|
2346
|
+
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
2347
|
+
appState: 'aftershow',
|
|
2348
|
+
});
|
|
2349
|
+
// dispatch aftershow event to base app
|
|
2350
|
+
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERSHOW);
|
|
2351
|
+
}
|
|
2298
2352
|
/**
|
|
2299
2353
|
* app rendering error
|
|
2300
2354
|
* @param e Error
|
|
@@ -2302,15 +2356,19 @@ class CreateApp {
|
|
|
2302
2356
|
onerror(e) {
|
|
2303
2357
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.ERROR, e);
|
|
2304
2358
|
}
|
|
2305
|
-
// get app
|
|
2306
|
-
|
|
2307
|
-
return this.
|
|
2359
|
+
// get app state
|
|
2360
|
+
getAppState() {
|
|
2361
|
+
return this.state;
|
|
2362
|
+
}
|
|
2363
|
+
// get keep-alive state
|
|
2364
|
+
getKeepAliveState() {
|
|
2365
|
+
return this.keepAliveState;
|
|
2308
2366
|
}
|
|
2309
2367
|
// get umd library, if it not exist, return empty object
|
|
2310
2368
|
getUmdLibraryHooks() {
|
|
2311
2369
|
var _a, _b;
|
|
2312
2370
|
// after execScripts, the app maybe unmounted
|
|
2313
|
-
if (
|
|
2371
|
+
if (appStates.UNMOUNT !== this.state) {
|
|
2314
2372
|
const global = ((_b = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow) !== null && _b !== void 0 ? _b : globalEnv.rawWindow);
|
|
2315
2373
|
this.libraryName = getRootContainer(this.container).getAttribute('library') || `micro-app-${this.name}`;
|
|
2316
2374
|
// do not use isObject
|
|
@@ -2323,7 +2381,7 @@ class CreateApp {
|
|
|
2323
2381
|
function getActiveApps() {
|
|
2324
2382
|
const activeApps = [];
|
|
2325
2383
|
appInstanceMap.forEach((app, appName) => {
|
|
2326
|
-
if (
|
|
2384
|
+
if (appStates.UNMOUNT !== app.getAppState() && !app.isPrefetch) {
|
|
2327
2385
|
activeApps.push(appName);
|
|
2328
2386
|
}
|
|
2329
2387
|
});
|
|
@@ -2700,7 +2758,7 @@ function rejectMicroAppStyle() {
|
|
|
2700
2758
|
}
|
|
2701
2759
|
|
|
2702
2760
|
function unmountNestedApp() {
|
|
2703
|
-
|
|
2761
|
+
releaseUnmountOfNestedApp();
|
|
2704
2762
|
appInstanceMap.forEach(app => {
|
|
2705
2763
|
// @ts-ignore
|
|
2706
2764
|
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
@@ -2718,7 +2776,7 @@ function listenUmountOfNestedApp() {
|
|
|
2718
2776
|
}
|
|
2719
2777
|
}
|
|
2720
2778
|
// release listener
|
|
2721
|
-
function
|
|
2779
|
+
function releaseUnmountOfNestedApp() {
|
|
2722
2780
|
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
2723
2781
|
window.removeEventListener('unmount', unmountNestedApp, false);
|
|
2724
2782
|
}
|
|
@@ -2745,7 +2803,6 @@ function defineElement(tagName) {
|
|
|
2745
2803
|
* handle for change of name an url after element inited
|
|
2746
2804
|
*/
|
|
2747
2805
|
this.handleAttributeUpdate = () => {
|
|
2748
|
-
var _a;
|
|
2749
2806
|
this.isWating = false;
|
|
2750
2807
|
const formatAttrName = formatAppName(this.getAttribute('name'));
|
|
2751
2808
|
const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
|
|
@@ -2753,44 +2810,27 @@ function defineElement(tagName) {
|
|
|
2753
2810
|
const existApp = appInstanceMap.get(formatAttrName);
|
|
2754
2811
|
if (formatAttrName !== this.appName && existApp) {
|
|
2755
2812
|
// handling of cached and non-prefetch apps
|
|
2756
|
-
if (
|
|
2813
|
+
if (appStates.UNMOUNT !== existApp.getAppState() &&
|
|
2814
|
+
keepAliveStates.KEEP_ALIVE_HIDDEN !== existApp.getKeepAliveState() &&
|
|
2815
|
+
!existApp.isPrefetch) {
|
|
2757
2816
|
this.setAttribute('name', this.appName);
|
|
2758
|
-
return logError(`an app named ${formatAttrName}
|
|
2817
|
+
return logError(`app name conflict, an app named ${formatAttrName} is running`, this.appName);
|
|
2759
2818
|
}
|
|
2760
2819
|
}
|
|
2761
2820
|
if (formatAttrName !== this.appName || formatAttrUrl !== this.appUrl) {
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
*/
|
|
2767
|
-
if (this.getDisposeResult('ssr')) {
|
|
2768
|
-
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, formatAttrUrl);
|
|
2769
|
-
}
|
|
2770
|
-
else if (this.ssrUrl) {
|
|
2771
|
-
this.ssrUrl = '';
|
|
2772
|
-
}
|
|
2773
|
-
this.appName = formatAttrName;
|
|
2774
|
-
this.appUrl = formatAttrUrl;
|
|
2775
|
-
((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this).innerHTML = '';
|
|
2776
|
-
if (formatAttrName !== this.getAttribute('name')) {
|
|
2777
|
-
this.setAttribute('name', this.appName);
|
|
2821
|
+
if (formatAttrName === this.appName) {
|
|
2822
|
+
this.handleUnmount(true, () => {
|
|
2823
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2824
|
+
});
|
|
2778
2825
|
}
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
* scene2: if formatAttrName and this.appName are different: existApp must be prefetch or unmounted, if url is equal, then just mount, if url is different, then create new app to replace existApp
|
|
2783
|
-
* scene3: url is different but ssrUrl is equal
|
|
2784
|
-
* scene4: url is equal but ssrUrl is different, if url is equal, name must different
|
|
2785
|
-
*/
|
|
2786
|
-
if (existApp &&
|
|
2787
|
-
existApp.url === this.appUrl &&
|
|
2788
|
-
existApp.ssrUrl === this.ssrUrl) {
|
|
2789
|
-
// mount app
|
|
2790
|
-
this.handleAppMount(existApp);
|
|
2826
|
+
else if (this.getDisposeResult('keep-alive')) {
|
|
2827
|
+
this.handleHiddenKeepAliveApp();
|
|
2828
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2791
2829
|
}
|
|
2792
2830
|
else {
|
|
2793
|
-
this.
|
|
2831
|
+
this.handleUnmount(this.getDisposeResult('destroy') || this.getDisposeResult('destory'), () => {
|
|
2832
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2833
|
+
});
|
|
2794
2834
|
}
|
|
2795
2835
|
}
|
|
2796
2836
|
}
|
|
@@ -2816,6 +2856,7 @@ function defineElement(tagName) {
|
|
|
2816
2856
|
// disableSandbox: whether disable sandbox, default is false
|
|
2817
2857
|
// macro: used to solve the async render problem of vue3, default is false
|
|
2818
2858
|
// baseRoute: route prefix, default is ''
|
|
2859
|
+
// keep-alive: open keep-alive mode, keep-alive has priority over destroy
|
|
2819
2860
|
connectedCallback() {
|
|
2820
2861
|
this.hasConnected = true;
|
|
2821
2862
|
if (!elementInstanceMap.has(this)) {
|
|
@@ -2826,10 +2867,17 @@ function defineElement(tagName) {
|
|
|
2826
2867
|
}
|
|
2827
2868
|
disconnectedCallback() {
|
|
2828
2869
|
this.hasConnected = false;
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2870
|
+
// keep-alive has priority over destroy
|
|
2871
|
+
if (this.getDisposeResult('keep-alive')) {
|
|
2872
|
+
this.handleHiddenKeepAliveApp();
|
|
2873
|
+
}
|
|
2874
|
+
else {
|
|
2875
|
+
elementInstanceMap.delete(this);
|
|
2876
|
+
this.handleUnmount(this.getDisposeResult('destroy') || this.getDisposeResult('destory'), () => {
|
|
2877
|
+
if (elementInstanceMap.size === 0) {
|
|
2878
|
+
releasePatches();
|
|
2879
|
+
}
|
|
2880
|
+
});
|
|
2833
2881
|
}
|
|
2834
2882
|
}
|
|
2835
2883
|
attributeChangedCallback(attr, _oldVal, newVal) {
|
|
@@ -2873,7 +2921,7 @@ function defineElement(tagName) {
|
|
|
2873
2921
|
if (elementInstanceMap.set(this, true).size === 1) {
|
|
2874
2922
|
patchElementPrototypeMethods();
|
|
2875
2923
|
rejectMicroAppStyle();
|
|
2876
|
-
|
|
2924
|
+
releaseUnmountOfNestedApp();
|
|
2877
2925
|
listenUmountOfNestedApp();
|
|
2878
2926
|
}
|
|
2879
2927
|
}
|
|
@@ -2892,15 +2940,21 @@ function defineElement(tagName) {
|
|
|
2892
2940
|
else if (this.ssrUrl) {
|
|
2893
2941
|
this.ssrUrl = '';
|
|
2894
2942
|
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2943
|
+
if (appInstanceMap.has(this.appName)) {
|
|
2944
|
+
const app = appInstanceMap.get(this.appName);
|
|
2897
2945
|
const existAppUrl = app.ssrUrl || app.url;
|
|
2898
2946
|
const activeAppUrl = this.ssrUrl || this.appUrl;
|
|
2899
|
-
|
|
2900
|
-
|
|
2947
|
+
// keep-alive don't care about ssrUrl
|
|
2948
|
+
// Even if the keep-alive app is pushed into the background, it is still active and cannot be replaced. Otherwise, it is difficult for developers to troubleshoot in case of conflict and will leave developers at a loss
|
|
2949
|
+
if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN &&
|
|
2950
|
+
app.url === this.appUrl) {
|
|
2951
|
+
this.handleShowKeepAliveApp(app);
|
|
2952
|
+
}
|
|
2953
|
+
else if (existAppUrl === activeAppUrl && (app.isPrefetch ||
|
|
2954
|
+
app.getAppState() === appStates.UNMOUNT)) {
|
|
2901
2955
|
this.handleAppMount(app);
|
|
2902
2956
|
}
|
|
2903
|
-
else if (app.isPrefetch || app.
|
|
2957
|
+
else if (app.isPrefetch || app.getAppState() === appStates.UNMOUNT) {
|
|
2904
2958
|
/**
|
|
2905
2959
|
* url is different & old app is unmounted or prefetch, create new app to replace old one
|
|
2906
2960
|
*/
|
|
@@ -2908,7 +2962,56 @@ function defineElement(tagName) {
|
|
|
2908
2962
|
this.handleCreateApp();
|
|
2909
2963
|
}
|
|
2910
2964
|
else {
|
|
2911
|
-
logError(`an app named ${this.appName}
|
|
2965
|
+
logError(`app name conflict, an app named ${this.appName} is running`, this.appName);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
else {
|
|
2969
|
+
this.handleCreateApp();
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
// remount app or create app if attribute url or name change
|
|
2973
|
+
actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp) {
|
|
2974
|
+
var _a;
|
|
2975
|
+
/**
|
|
2976
|
+
* change ssrUrl in ssr mode
|
|
2977
|
+
* do not add judgment of formatAttrUrl === this.appUrl
|
|
2978
|
+
*/
|
|
2979
|
+
if (this.getDisposeResult('ssr')) {
|
|
2980
|
+
this.ssrUrl = CompletionPath(globalEnv.rawWindow.location.pathname, formatAttrUrl);
|
|
2981
|
+
}
|
|
2982
|
+
else if (this.ssrUrl) {
|
|
2983
|
+
this.ssrUrl = '';
|
|
2984
|
+
}
|
|
2985
|
+
this.appName = formatAttrName;
|
|
2986
|
+
this.appUrl = formatAttrUrl;
|
|
2987
|
+
((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this).innerHTML = '';
|
|
2988
|
+
if (formatAttrName !== this.getAttribute('name')) {
|
|
2989
|
+
this.setAttribute('name', this.appName);
|
|
2990
|
+
}
|
|
2991
|
+
/**
|
|
2992
|
+
* when existApp not null: this.appName === existApp.name
|
|
2993
|
+
* scene1: if formatAttrName and this.appName are equal: exitApp is the current app, the url must be different, existApp has been unmounted
|
|
2994
|
+
* scene2: if formatAttrName and this.appName are different: existApp must be prefetch or unmounted, if url is equal, then just mount, if url is different, then create new app to replace existApp
|
|
2995
|
+
* scene3: url is different but ssrUrl is equal
|
|
2996
|
+
* scene4: url is equal but ssrUrl is different, if url is equal, name must different
|
|
2997
|
+
* scene5: if existApp is KEEP_ALIVE_HIDDEN, name must different
|
|
2998
|
+
*/
|
|
2999
|
+
if (existApp) {
|
|
3000
|
+
if (existApp.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
3001
|
+
if (existApp.url === this.appUrl) {
|
|
3002
|
+
this.handleShowKeepAliveApp(existApp);
|
|
3003
|
+
}
|
|
3004
|
+
else {
|
|
3005
|
+
// the hidden keep-alive app is still active
|
|
3006
|
+
logError(`app name conflict, an app named ${this.appName} is running`, this.appName);
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
else if (existApp.url === this.appUrl && existApp.ssrUrl === this.ssrUrl) {
|
|
3010
|
+
// mount app
|
|
3011
|
+
this.handleAppMount(existApp);
|
|
3012
|
+
}
|
|
3013
|
+
else {
|
|
3014
|
+
this.handleCreateApp();
|
|
2912
3015
|
}
|
|
2913
3016
|
}
|
|
2914
3017
|
else {
|
|
@@ -2968,10 +3071,24 @@ function defineElement(tagName) {
|
|
|
2968
3071
|
* unmount app
|
|
2969
3072
|
* @param destroy delete cache resources when unmount
|
|
2970
3073
|
*/
|
|
2971
|
-
handleUnmount(destroy) {
|
|
3074
|
+
handleUnmount(destroy, unmountcb) {
|
|
3075
|
+
const app = appInstanceMap.get(this.appName);
|
|
3076
|
+
if (app &&
|
|
3077
|
+
app.getAppState() !== appStates.UNMOUNT)
|
|
3078
|
+
app.unmount(destroy, unmountcb);
|
|
3079
|
+
}
|
|
3080
|
+
// hidden app when disconnectedCallback called with keep-alive
|
|
3081
|
+
handleHiddenKeepAliveApp() {
|
|
2972
3082
|
const app = appInstanceMap.get(this.appName);
|
|
2973
|
-
if (app &&
|
|
2974
|
-
app.
|
|
3083
|
+
if (app &&
|
|
3084
|
+
app.getAppState() !== appStates.UNMOUNT &&
|
|
3085
|
+
app.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN)
|
|
3086
|
+
app.hiddenKeepAliveApp();
|
|
3087
|
+
}
|
|
3088
|
+
// show app when connectedCallback called with keep-alive
|
|
3089
|
+
handleShowKeepAliveApp(app) {
|
|
3090
|
+
// must be asnyc
|
|
3091
|
+
defer(() => { var _a; return app.showKeepAliveApp((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this); });
|
|
2975
3092
|
}
|
|
2976
3093
|
/**
|
|
2977
3094
|
* Get configuration
|