diff --git a/packages/fes-plugin-qiankun/examples/main/src/pages/index.vue b/packages/fes-plugin-qiankun/examples/main/src/pages/index.vue
index e1f1c676..6bbe5a4e 100644
--- a/packages/fes-plugin-qiankun/examples/main/src/pages/index.vue
+++ b/packages/fes-plugin-qiankun/examples/main/src/pages/index.vue
@@ -2,6 +2,7 @@
main
+
{
@@ -9,3 +10,22 @@
"title": "首页"
}
+
diff --git a/packages/fes-plugin-qiankun/src/main/index.js b/packages/fes-plugin-qiankun/src/main/index.js
index 5ee3f2d1..3f4b035e 100644
--- a/packages/fes-plugin-qiankun/src/main/index.js
+++ b/packages/fes-plugin-qiankun/src/main/index.js
@@ -33,6 +33,7 @@ export default function (api) {
modifyRoutes({ api, namespace });
const absMicroAppPath = join(namespace, 'MicroApp.js');
+ const absMicroAppWithMemoHistoryPath = join(namespace, 'MicroAppWithMemoHistory.js');
const absRuntimePath = join(namespace, 'runtime.js');
const absMasterOptionsPath = join(namespace, 'masterOptions.js');
const absGetMicroAppRouteCompPath = join(
@@ -62,6 +63,15 @@ export default function (api) {
)
});
+ api.writeTmpFile({
+ path: absMicroAppWithMemoHistoryPath,
+ content: Mustache.render(
+ readFileSync(join(__dirname, 'runtime/MicroAppWithMemoHistory.tpl'), 'utf-8'),
+ {
+ }
+ )
+ });
+
api.writeTmpFile({
path: absRuntimePath,
content: readFileSync(
@@ -102,6 +112,13 @@ export default function (api) {
}
]);
+ api.addPluginExports(() => [
+ {
+ specifiers: ['MicroAppWithMemoHistory'],
+ source: absMicroAppWithMemoHistoryPath
+ }
+ ]);
+
api.addPluginExports(() => [
{
specifiers: ['getMicroAppRouteComponent'],
diff --git a/packages/fes-plugin-qiankun/src/main/runtime/MicroApp.tpl b/packages/fes-plugin-qiankun/src/main/runtime/MicroApp.tpl
index 9c642047..69266cf1 100644
--- a/packages/fes-plugin-qiankun/src/main/runtime/MicroApp.tpl
+++ b/packages/fes-plugin-qiankun/src/main/runtime/MicroApp.tpl
@@ -13,15 +13,12 @@ import mergeWith from "lodash/mergeWith";
import { getMasterOptions } from "./masterOptions";
import { onBeforeRouteLeave } from "@@/core/coreExports";
-let unmountPromise;
async function unmountMicroApp(microApp) {
if (microApp) {
- return microApp.mountPromise.then(_microApp => {
- // Now it is safe to call unmount
- if(_microApp){
- return _microApp.unmount()
- }
- })
+ const status = microApp.getStatus();
+ if(status === 'MOUNTED'){
+ await microApp.unmount();
+ }
}
return Promise.resolve();
}
diff --git a/packages/fes-plugin-qiankun/src/main/runtime/MicroAppWithMemoHistory.tpl b/packages/fes-plugin-qiankun/src/main/runtime/MicroAppWithMemoHistory.tpl
new file mode 100644
index 00000000..8aefa40d
--- /dev/null
+++ b/packages/fes-plugin-qiankun/src/main/runtime/MicroAppWithMemoHistory.tpl
@@ -0,0 +1,33 @@
+
+import {
+ defineComponent, isRef, watch
+} from 'vue';
+import { MicroApp } from './MicroApp';
+
+
+export const MicroAppWithMemoHistory = defineComponent({
+ components: {
+ MicroApp
+ },
+ props: {
+ name: {
+ type: String,
+ required: true
+ },
+ settings: Object,
+ lifeCycles: Object,
+ className: String,
+ url: String
+ },
+ setup(props, { attrs }) {
+ let microRouter;
+ const onRouterInit = (router) => {
+ microRouter = router;
+ microRouter.push(props.url);
+ };
+ watch(()=>props.url, () => {
+ microRouter.push(props.url);
+ });
+ return () => ;
+ }
+});
diff --git a/packages/fes-plugin-qiankun/src/micro/index.js b/packages/fes-plugin-qiankun/src/micro/index.js
index 2bcd85d2..855385ee 100644
--- a/packages/fes-plugin-qiankun/src/micro/index.js
+++ b/packages/fes-plugin-qiankun/src/micro/index.js
@@ -155,6 +155,8 @@ export default function (api) {
}
});
+ api.addRuntimePlugin(() => `@@/${absRuntimePath}`);
+
api.addEntryImports(() => ({
source: `@@/${absLifeclesPath}`,
specifier:
diff --git a/packages/fes-plugin-qiankun/src/micro/runtime/lifecycles.tpl b/packages/fes-plugin-qiankun/src/micro/runtime/lifecycles.tpl
index b429733c..807ce787 100644
--- a/packages/fes-plugin-qiankun/src/micro/runtime/lifecycles.tpl
+++ b/packages/fes-plugin-qiankun/src/micro/runtime/lifecycles.tpl
@@ -1,4 +1,4 @@
-import { plugin, ApplyPluginsType } from '@@/core/coreExports';
+import { plugin, ApplyPluginsType, getRouter, getHistory, destroyRouter } from '@@/core/coreExports';
{{#HAS_PLUGIN_MODEL}}
import { setModelState } from './qiankunModel';
{{/HAS_PLUGIN_MODEL}}
@@ -21,6 +21,10 @@ let hasMountedAtLeastOnce = false;
export default () => defer.promise;
+export const clientRenderOptsStack = [];
+
+export const history = {};
+
function getSlaveRuntime() {
const config = plugin.applyPlugins({
key: 'qiankun',
@@ -59,6 +63,23 @@ export function genMount(mountElementId) {
}
}
+ // 更新 clientRender 配置
+ const clientRenderOpts = {
+ // 支持通过 props 注入 container 来限定子应用 mountElementId 的查找范围
+ // 避免多个子应用出现在同一主应用时出现 mount 冲突
+ rootElement:
+ props?.container?.querySelector(mountElementId) || mountElementId
+ };
+
+ clientRenderOptsStack.push(clientRenderOpts);
+
+ if(props.url){
+ history.url = props.url || '/';
+ }
+ if(props.onRouterInit){
+ history.onRouterInit = props.onRouterInit;
+ }
+
// 第一次 mount 会自动触发 render,非第一次 mount 则需手动触发
if (hasMountedAtLeastOnce) {
const appPromise = render();
@@ -87,10 +108,13 @@ export function genUpdate() {
// 子应用生命周期钩子Unmount
export function genUnmount() {
return async (props) => {
+ const history = getHistory();
+ history.destroy();
if (cacheAppPromise) {
const app = await cacheAppPromise;
app.unmount();
}
+ destroyRouter();
const slaveRuntime = getSlaveRuntime();
if (slaveRuntime.unmount) {
await slaveRuntime.unmount(props);
diff --git a/packages/fes-plugin-qiankun/src/micro/runtime/runtime.tpl b/packages/fes-plugin-qiankun/src/micro/runtime/runtime.tpl
index e69de29b..d8e62d47 100644
--- a/packages/fes-plugin-qiankun/src/micro/runtime/runtime.tpl
+++ b/packages/fes-plugin-qiankun/src/micro/runtime/runtime.tpl
@@ -0,0 +1,31 @@
+import { createMemoryHistory } from '@@/core/coreExports';
+import qiankunRender, { clientRenderOptsStack, history } from './lifecycles';
+
+
+export const render = oldRender => qiankunRender().then(oldRender);
+
+export function modifyClientRenderOpts(memo) {
+ // 每次应用 render 的时候会调 modifyClientRenderOpts,这时尝试从队列中取 render 的配置
+ const clientRenderOpts = clientRenderOptsStack.shift();
+
+ return {
+ ...memo,
+ ...clientRenderOpts
+ };
+}
+
+export function modifyHistroy(memo) {
+ if (history.url) {
+ const memoHistroy = createMemoryHistory();
+ memoHistroy.push(history.url)
+ return memoHistroy
+ }
+ return memo;
+}
+
+export function onRouterCreated({ router }) {
+ if(history.onRouterInit){
+ history.onRouterInit(router)
+ }
+}
+
diff --git a/packages/fes-preset-built-in/src/plugins/generateFiles/core/plugin/index.js b/packages/fes-preset-built-in/src/plugins/generateFiles/core/plugin/index.js
index e574df9e..2680eff5 100644
--- a/packages/fes-preset-built-in/src/plugins/generateFiles/core/plugin/index.js
+++ b/packages/fes-preset-built-in/src/plugins/generateFiles/core/plugin/index.js
@@ -18,6 +18,7 @@ export default function (api) {
initialValue: [
// 初始化数据
'beforeRender',
+ // modify渲染工具
'modifyClientRenderOpts',
'rootContainer',
// app生成时触发
@@ -26,6 +27,8 @@ export default function (api) {
'render',
// 修改路由
'patchRoutes',
+ // 修改histror
+ 'modifyHistroy',
// 生成router时触发
'onRouterCreated'
]
@@ -48,7 +51,7 @@ export default function (api) {
{
validKeys,
runtimePath
- },
+ }
)
});
api.writeTmpFile({
@@ -60,7 +63,7 @@ export default function (api) {
index,
path: winPath(plugin)
}))
- },
+ }
)
});
});
diff --git a/packages/fes-preset-built-in/src/plugins/misc/route/index.js b/packages/fes-preset-built-in/src/plugins/misc/route/index.js
index 5debe708..37ac9a22 100644
--- a/packages/fes-preset-built-in/src/plugins/misc/route/index.js
+++ b/packages/fes-preset-built-in/src/plugins/misc/route/index.js
@@ -293,7 +293,7 @@ export default function (api) {
api.addCoreExports(() => [
{
- specifiers: ['getRoutes', 'getRouter', 'getHistory'],
+ specifiers: ['getRoutes', 'getRouter', 'getHistory', 'destroyRouter'],
source: absCoreFilePath
}
]);
diff --git a/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl b/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl
index ea47d11c..3e134cd6 100644
--- a/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl
+++ b/packages/fes-preset-built-in/src/plugins/misc/route/template/routes.tpl
@@ -20,7 +20,11 @@ export const createRouter = () => {
if (router) {
return router;
}
- history = {{{ CREATE_HISTORY }}}(ROUTER_BASE)
+ history = plugin.applyPlugins({
+ key: 'modifyHistroy',
+ type: ApplyPluginsType.modify,
+ initialValue: {{{ CREATE_HISTORY }}}(ROUTER_BASE),
+ });
router = createVueRouter({
history,
routes: getRoutes()
@@ -36,9 +40,20 @@ export const createRouter = () => {
};
export const getRouter = ()=>{
- return router;
+ if(!router){
+ console.warn(`[preset-build-in] router is null`)
+ }
+ return router;
}
export const getHistory = ()=>{
- return history;
+ if(!history){
+ console.warn(`[preset-build-in] history is null`)
+ }
+ return history;
+}
+
+export const destroyRouter = ()=>{
+ router = null;
+ history = null;
}