mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-04-06 03:59:53 +08:00
161 lines
5.2 KiB
Smarty
161 lines
5.2 KiB
Smarty
import {
|
||
defineComponent,
|
||
ref,
|
||
reactive,
|
||
watch,
|
||
computed,
|
||
onBeforeUnmount,
|
||
onMounted,
|
||
} from "vue";
|
||
import { loadMicroApp } from "{{{QIANKUN}}}";
|
||
import {mergeWith} from "{{{LODASH_ES}}}";
|
||
// eslint-disable-next-line import/extensions
|
||
import { getMasterOptions } from "./masterOptions";
|
||
|
||
function unmountMicroApp(microApp) {
|
||
if (!microApp) {
|
||
return;
|
||
}
|
||
const status = microApp.getStatus();
|
||
if (status === 'MOUNTED') {
|
||
microApp.unmount();
|
||
}
|
||
}
|
||
|
||
export const MicroApp = defineComponent({
|
||
props: {
|
||
name: {
|
||
type: String,
|
||
required: true
|
||
},
|
||
settings: Object,
|
||
props: Object,
|
||
lifeCycles: Object
|
||
},
|
||
setup(props, { attrs }) {
|
||
const {
|
||
masterHistoryType,
|
||
apps = [],
|
||
lifeCycles: globalLifeCycles,
|
||
...globalSettings
|
||
} = getMasterOptions();
|
||
|
||
// 挂载节点
|
||
const containerRef = ref(null);
|
||
const microAppRef = ref();
|
||
const updatingPromiseRef = ref();
|
||
const updatingTimestampRef = ref(Date.now());
|
||
|
||
const appConfigRef = computed(() => {
|
||
const appConfig = apps.find((app) => app.name === props.name);
|
||
if (!appConfig) {
|
||
throw new Error(
|
||
`[@fesjs/plugin-qiankun]: Can not find the configuration of ${props.name} app!`
|
||
);
|
||
}
|
||
return appConfig;
|
||
});
|
||
|
||
const propsFromConfigRef = computed(() => {
|
||
const appConfig = appConfigRef.value;
|
||
if (appConfig) {
|
||
return appConfig.props;
|
||
}
|
||
return {};
|
||
});
|
||
|
||
const propsConfigRef = computed(() => {
|
||
return {
|
||
...propsFromConfigRef.value,
|
||
...props.props,
|
||
...attrs
|
||
};
|
||
});
|
||
|
||
// 只有当name变化时才重新加载新的子应用
|
||
const loadApp = () => {
|
||
const appConfig = appConfigRef.value;
|
||
const { name, entry } = appConfig;
|
||
// 加载新的
|
||
microAppRef.value = loadMicroApp(
|
||
{
|
||
// 保证唯一
|
||
name: `${name}_${Date.now()}`,
|
||
entry: entry,
|
||
container: containerRef.value,
|
||
props: {...propsConfigRef.value}
|
||
},
|
||
{
|
||
...globalSettings,
|
||
...(props.settings || {})
|
||
},
|
||
mergeWith(
|
||
{},
|
||
globalLifeCycles || {},
|
||
props.lifeCycles || {},
|
||
(v1, v2) => concat(v1 ?? [], v2 ?? [])
|
||
)
|
||
);
|
||
};
|
||
|
||
// 当参数变化时,update子应用
|
||
const updateApp = () => {
|
||
const microApp = microAppRef.value;
|
||
if (microApp) {
|
||
if (!updatingPromiseRef.value) {
|
||
// 初始化 updatingPromiseRef 为 microApp.mountPromise,从而确保后续更新是在应用 mount 完成之后
|
||
updatingPromiseRef.value = microApp.mountPromise;
|
||
}
|
||
// 确保 microApp.update 调用是跟组件状态变更顺序一致的,且后一个微应用更新必须等待前一个更新完成
|
||
updatingPromiseRef.value = updatingPromiseRef.value.then(
|
||
() => {
|
||
const canUpdate = (app) =>
|
||
app?.update && app.getStatus() === 'MOUNTED';
|
||
if (canUpdate(microApp)) {
|
||
if (process.env.NODE_ENV === 'development') {
|
||
if (
|
||
Date.now() -
|
||
updatingTimestampRef.value <
|
||
200
|
||
) {
|
||
console.warn(
|
||
`[@fesjs/plugin-qiankun] It seems like microApp ${props.name} is updating too many times in a short time(200ms), you may need to do some optimization to avoid the unnecessary re-rendering.`
|
||
);
|
||
}
|
||
|
||
console.info(
|
||
`[@fesjs/plugin-qiankun] MicroApp ${props.name} is updating with props: `,
|
||
props
|
||
);
|
||
updatingTimestampRef.value = Date.now();
|
||
}
|
||
|
||
// 返回 microApp.update 形成链式调用
|
||
return microApp.update({...propsConfigRef.value});
|
||
}
|
||
}
|
||
);
|
||
}
|
||
};
|
||
|
||
onMounted(() => {
|
||
loadApp();
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
unmountMicroApp(microAppRef.value);
|
||
});
|
||
|
||
watch(appConfigRef, () => {
|
||
unmountMicroApp(microAppRef.value);
|
||
loadApp();
|
||
});
|
||
|
||
watch(propsConfigRef, () => {
|
||
updateApp();
|
||
});
|
||
|
||
return () => <div ref={containerRef}></div>;
|
||
}
|
||
});
|