mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-04-06 03:59:53 +08:00
Merge branch 'qiankun' into vue3
This commit is contained in:
commit
daeb5aab04
@ -2,6 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
main
|
main
|
||||||
</div>
|
</div>
|
||||||
|
<MicroAppWithMemoHistory name="app1" :url="url" />
|
||||||
</template>
|
</template>
|
||||||
<config>
|
<config>
|
||||||
{
|
{
|
||||||
@ -9,3 +10,22 @@
|
|||||||
"title": "首页"
|
"title": "首页"
|
||||||
}
|
}
|
||||||
</config>
|
</config>
|
||||||
|
<script>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { MicroAppWithMemoHistory } from '@fesjs/fes';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { MicroAppWithMemoHistory },
|
||||||
|
setup() {
|
||||||
|
const url = ref('/app1/test');
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
url.value = '/app1';
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
@ -33,6 +33,7 @@ export default function (api) {
|
|||||||
modifyRoutes({ api, namespace });
|
modifyRoutes({ api, namespace });
|
||||||
|
|
||||||
const absMicroAppPath = join(namespace, 'MicroApp.js');
|
const absMicroAppPath = join(namespace, 'MicroApp.js');
|
||||||
|
const absMicroAppWithMemoHistoryPath = join(namespace, 'MicroAppWithMemoHistory.js');
|
||||||
const absRuntimePath = join(namespace, 'runtime.js');
|
const absRuntimePath = join(namespace, 'runtime.js');
|
||||||
const absMasterOptionsPath = join(namespace, 'masterOptions.js');
|
const absMasterOptionsPath = join(namespace, 'masterOptions.js');
|
||||||
const absGetMicroAppRouteCompPath = join(
|
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({
|
api.writeTmpFile({
|
||||||
path: absRuntimePath,
|
path: absRuntimePath,
|
||||||
content: readFileSync(
|
content: readFileSync(
|
||||||
@ -102,6 +112,13 @@ export default function (api) {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
api.addPluginExports(() => [
|
||||||
|
{
|
||||||
|
specifiers: ['MicroAppWithMemoHistory'],
|
||||||
|
source: absMicroAppWithMemoHistoryPath
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
api.addPluginExports(() => [
|
api.addPluginExports(() => [
|
||||||
{
|
{
|
||||||
specifiers: ['getMicroAppRouteComponent'],
|
specifiers: ['getMicroAppRouteComponent'],
|
||||||
|
@ -13,15 +13,12 @@ import mergeWith from "lodash/mergeWith";
|
|||||||
import { getMasterOptions } from "./masterOptions";
|
import { getMasterOptions } from "./masterOptions";
|
||||||
import { onBeforeRouteLeave } from "@@/core/coreExports";
|
import { onBeforeRouteLeave } from "@@/core/coreExports";
|
||||||
|
|
||||||
let unmountPromise;
|
|
||||||
async function unmountMicroApp(microApp) {
|
async function unmountMicroApp(microApp) {
|
||||||
if (microApp) {
|
if (microApp) {
|
||||||
return microApp.mountPromise.then(_microApp => {
|
const status = microApp.getStatus();
|
||||||
// Now it is safe to call unmount
|
if(status === 'MOUNTED'){
|
||||||
if(_microApp){
|
await microApp.unmount();
|
||||||
return _microApp.unmount()
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -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 () => <MicroApp onRouterInit={onRouterInit} {...props} {...attrs}></MicroApp>;
|
||||||
|
}
|
||||||
|
});
|
@ -155,6 +155,8 @@ export default function (api) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.addRuntimePlugin(() => `@@/${absRuntimePath}`);
|
||||||
|
|
||||||
api.addEntryImports(() => ({
|
api.addEntryImports(() => ({
|
||||||
source: `@@/${absLifeclesPath}`,
|
source: `@@/${absLifeclesPath}`,
|
||||||
specifier:
|
specifier:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { plugin, ApplyPluginsType } from '@@/core/coreExports';
|
import { plugin, ApplyPluginsType, getRouter, getHistory, destroyRouter } from '@@/core/coreExports';
|
||||||
{{#HAS_PLUGIN_MODEL}}
|
{{#HAS_PLUGIN_MODEL}}
|
||||||
import { setModelState } from './qiankunModel';
|
import { setModelState } from './qiankunModel';
|
||||||
{{/HAS_PLUGIN_MODEL}}
|
{{/HAS_PLUGIN_MODEL}}
|
||||||
@ -21,6 +21,10 @@ let hasMountedAtLeastOnce = false;
|
|||||||
|
|
||||||
export default () => defer.promise;
|
export default () => defer.promise;
|
||||||
|
|
||||||
|
export const clientRenderOptsStack = [];
|
||||||
|
|
||||||
|
export const history = {};
|
||||||
|
|
||||||
function getSlaveRuntime() {
|
function getSlaveRuntime() {
|
||||||
const config = plugin.applyPlugins({
|
const config = plugin.applyPlugins({
|
||||||
key: 'qiankun',
|
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 则需手动触发
|
// 第一次 mount 会自动触发 render,非第一次 mount 则需手动触发
|
||||||
if (hasMountedAtLeastOnce) {
|
if (hasMountedAtLeastOnce) {
|
||||||
const appPromise = render();
|
const appPromise = render();
|
||||||
@ -87,10 +108,13 @@ export function genUpdate() {
|
|||||||
// 子应用生命周期钩子Unmount
|
// 子应用生命周期钩子Unmount
|
||||||
export function genUnmount() {
|
export function genUnmount() {
|
||||||
return async (props) => {
|
return async (props) => {
|
||||||
|
const history = getHistory();
|
||||||
|
history.destroy();
|
||||||
if (cacheAppPromise) {
|
if (cacheAppPromise) {
|
||||||
const app = await cacheAppPromise;
|
const app = await cacheAppPromise;
|
||||||
app.unmount();
|
app.unmount();
|
||||||
}
|
}
|
||||||
|
destroyRouter();
|
||||||
const slaveRuntime = getSlaveRuntime();
|
const slaveRuntime = getSlaveRuntime();
|
||||||
if (slaveRuntime.unmount) {
|
if (slaveRuntime.unmount) {
|
||||||
await slaveRuntime.unmount(props);
|
await slaveRuntime.unmount(props);
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ export default function (api) {
|
|||||||
initialValue: [
|
initialValue: [
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
'beforeRender',
|
'beforeRender',
|
||||||
|
// modify渲染工具
|
||||||
'modifyClientRenderOpts',
|
'modifyClientRenderOpts',
|
||||||
'rootContainer',
|
'rootContainer',
|
||||||
// app生成时触发
|
// app生成时触发
|
||||||
@ -26,6 +27,8 @@ export default function (api) {
|
|||||||
'render',
|
'render',
|
||||||
// 修改路由
|
// 修改路由
|
||||||
'patchRoutes',
|
'patchRoutes',
|
||||||
|
// 修改histror
|
||||||
|
'modifyHistroy',
|
||||||
// 生成router时触发
|
// 生成router时触发
|
||||||
'onRouterCreated'
|
'onRouterCreated'
|
||||||
]
|
]
|
||||||
@ -48,7 +51,7 @@ export default function (api) {
|
|||||||
{
|
{
|
||||||
validKeys,
|
validKeys,
|
||||||
runtimePath
|
runtimePath
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
api.writeTmpFile({
|
api.writeTmpFile({
|
||||||
@ -60,7 +63,7 @@ export default function (api) {
|
|||||||
index,
|
index,
|
||||||
path: winPath(plugin)
|
path: winPath(plugin)
|
||||||
}))
|
}))
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -293,7 +293,7 @@ export default function (api) {
|
|||||||
|
|
||||||
api.addCoreExports(() => [
|
api.addCoreExports(() => [
|
||||||
{
|
{
|
||||||
specifiers: ['getRoutes', 'getRouter', 'getHistory'],
|
specifiers: ['getRoutes', 'getRouter', 'getHistory', 'destroyRouter'],
|
||||||
source: absCoreFilePath
|
source: absCoreFilePath
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -20,7 +20,11 @@ export const createRouter = () => {
|
|||||||
if (router) {
|
if (router) {
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
history = {{{ CREATE_HISTORY }}}(ROUTER_BASE)
|
history = plugin.applyPlugins({
|
||||||
|
key: 'modifyHistroy',
|
||||||
|
type: ApplyPluginsType.modify,
|
||||||
|
initialValue: {{{ CREATE_HISTORY }}}(ROUTER_BASE),
|
||||||
|
});
|
||||||
router = createVueRouter({
|
router = createVueRouter({
|
||||||
history,
|
history,
|
||||||
routes: getRoutes()
|
routes: getRoutes()
|
||||||
@ -36,9 +40,20 @@ export const createRouter = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getRouter = ()=>{
|
export const getRouter = ()=>{
|
||||||
return router;
|
if(!router){
|
||||||
|
console.warn(`[preset-build-in] router is null`)
|
||||||
|
}
|
||||||
|
return router;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getHistory = ()=>{
|
export const getHistory = ()=>{
|
||||||
return history;
|
if(!history){
|
||||||
|
console.warn(`[preset-build-in] history is null`)
|
||||||
|
}
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const destroyRouter = ()=>{
|
||||||
|
router = null;
|
||||||
|
history = null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user