Skip to content

Commit

Permalink
fix(vue): add unmount hook to unmount application (#2849)
Browse files Browse the repository at this point in the history
  • Loading branch information
linghaoSu authored Jan 28, 2024
1 parent fb91153 commit f6926d3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-parents-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@qiankunjs/vue": patch
---

fix(vue): add unmount hook to unmount application
37 changes: 31 additions & 6 deletions examples/main/render/Vue3Render.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,48 @@
import { createApp, h } from 'vue';
import { createApp, h, onBeforeMount, onBeforeUnmount, ref } from 'vue';
import { MicroApp } from '../../../packages/ui-bindings/vue/dist/esm';

const sidemenu = document.querySelector('.mainapp-sidemenu');

const microApps = [
{ name: 'react15', entry: '//localhost:7102' },
{ name: 'react16', entry: '//localhost:7100' },
];

function vueRender() {
const application = createApp({
components: {
},
render() {
return h('div', [
this.message,
h(MicroApp, { name: 'react15', entry: '//localhost:7102' }),
this.message,
h(MicroApp, { name: this.name, entry: this.entry, autoCaptureError: true }),
]);
},
setup() {
const message = 'abc';
const name = ref('');
const entry = ref('');

const handleMenuClick = (e) => {
const app = microApps.find((app) => app.name === e.target.dataset.value);
if (app && app.name !== name.value) {
name.value = app.name;
entry.value = app.entry;
} else {
console.log('not found any app');
}
}

onBeforeMount(() => {
sidemenu.addEventListener('click', handleMenuClick);
});


onBeforeUnmount(() => {
sidemenu.removeEventListener('click', handleMenuClick);
});

return {
message,
name,
entry,
};
// return () => h('div', [
// message.value,
Expand Down
1 change: 1 addition & 0 deletions packages/ui-bindings/vue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ import { MicroApp } from '@qiankunjs/vue';
| `autoCaptureError` | No | Automatically set error capturing for the micro-application | `boolean` | `false` |
| `className` | No | The style class for the micro-application | `string` | `undefined` |
| `wrapperClassName` | No | The style class wrapping the micro-application's loading and error components | `string` | `undefined` |
| `appProps` | No | Properties passed to the sub-application | `Record<string, any>` | `undefined` |

### Component Slots

Expand Down
1 change: 1 addition & 0 deletions packages/ui-bindings/vue/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import { MicroApp } from '@qiankunjs/vue';
| `autoCaptureError` || 自动设置微应用的错误捕获 | `boolean` | `false` |
| `className` || 微应用的样式类 | `string` | `undefined` |
| `wrapperClassName` || 包裹微应用加载组件、错误捕获组件和微应用的样式类,仅在启用加载组件或错误捕获组件时有效 | `string` | `undefined` |
| `appProps` || 传递给子应用的属性 | `Record<string, any>` | `undefined` |

### 组件插槽

Expand Down
88 changes: 55 additions & 33 deletions packages/ui-bindings/vue/src/MicroApp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import type { PropType } from 'vue-demi';
import { computed, defineComponent, h, onMounted, reactive, ref, toRefs, watch, isVue2 } from 'vue-demi';
import {
computed,
defineComponent,
h,
onMounted,
ref,
onBeforeUnmount,
shallowRef,
toRefs,
watch,
isVue2,
} from 'vue-demi';
import type { AppConfiguration, LifeCycles } from 'qiankun';
import type { MicroAppType } from '@qiankunjs/ui-shared';
import { mountMicroApp, omitSharedProps, unmountMicroApp, updateMicroApp } from '@qiankunjs/ui-shared';
Expand Down Expand Up @@ -43,23 +54,23 @@ export const MicroApp = defineComponent({
type: String,
default: undefined,
},
appProps: {
type: Object,
default: undefined,
},
},
setup(props, { slots }) {
const originProps = props;
const { name, wrapperClassName, className, ...propsFromParams } = toRefs(originProps);
const { name, wrapperClassName, className, appProps, autoCaptureError } = toRefs(originProps);

const loading = ref(false);
const error = ref<Error>();

const containerRef = ref(null);
const microAppRef = ref<MicroAppType>();

const reactivePropsFromParams = computed(() => {
return omitSharedProps(reactive(propsFromParams));
});
const microAppRef = shallowRef<MicroAppType>();

const isNeedShowError = computed(() => {
return slots.errorBoundary || reactivePropsFromParams.value.autoCaptureError;
return slots.errorBoundary || autoCaptureError.value;
});

// 配置了 errorBoundary 才改 error 状态,否则直接往上抛异常
Expand All @@ -77,31 +88,38 @@ export const MicroApp = defineComponent({

const rootRef = ref(null);

onMounted(() => {
console.log(rootRef.value);
const unmount = () => {
const microApp = microAppRef.value;

console.log(containerRef.value);
if (microApp) {
microApp._unmounting = true;

unmountMicroApp(microApp).catch((err: Error) => {
setComponentError(err);
loading.value = false;
});

microAppRef.value = undefined;
}
};

onMounted(() => {
// watch name 变更切换子应用
watch(
name,
() => {
const microApp = microAppRef.value;

if (microApp) {
microApp._unmounting = true;

unmountMicroApp(microApp).catch((err: Error) => {
setComponentError(err);
loading.value = false;
});

microAppRef.value = undefined;
}
const prevApp = microAppRef.value;
// 销毁上一个子应用
unmount();

// 初始化下一个子应用
void mountMicroApp({
prevMicroApp: microAppRef.value,
prevMicroApp: prevApp,
container: containerRef.value!,
componentProps: originProps,
componentProps: {
...originProps,
...appProps.value,
},
setLoading: (l) => {
loading.value = l;
},
Expand All @@ -118,13 +136,17 @@ export const MicroApp = defineComponent({
);

watch(
reactivePropsFromParams,
appProps,
() => {
updateMicroApp({
microApp: microAppRef.value,
setLoading: (l) => {
loading.value = l;
},
microAppProps: {
...omitSharedProps(originProps),
...appProps.value,
},
});
},
{
Expand All @@ -133,6 +155,10 @@ export const MicroApp = defineComponent({
);
});

onBeforeUnmount(() => {
unmount();
});

const microAppWrapperClassName = computed(() =>
wrapperClassName.value ? `${wrapperClassName.value} qiankun-micro-app-wrapper` : 'qiankun-micro-app-wrapper',
);
Expand All @@ -149,16 +175,12 @@ export const MicroApp = defineComponent({
microAppWrapperClassName,
microAppClassName,
rootRef,
reactivePropsFromParams,
microApp: microAppRef,
};
},

render() {
return this.reactivePropsFromParams.autoSetLoading ||
this.reactivePropsFromParams.autoCaptureError ||
this.$slots.loader ||
this.$slots.errorBoundary
return this.autoSetLoading || this.autoCaptureError || this.$slots.loader || this.$slots.errorBoundary
? h(
'div',
{
Expand All @@ -169,7 +191,7 @@ export const MicroApp = defineComponent({
? typeof this.$slots.loader === 'function'
? this.$slots.loader(this.loading)
: this.$slots.loader
: this.reactivePropsFromParams.autoSetLoading &&
: this.autoSetLoading &&
h(MicroAppLoader, {
...(isVue2
? {
Expand All @@ -186,7 +208,7 @@ export const MicroApp = defineComponent({
? typeof this.$slots.errorBoundary === 'function'
? this.$slots.errorBoundary(this.error)
: this.$slots.errorBoundary
: this.reactivePropsFromParams.autoCaptureError &&
: this.autoCaptureError &&
h(ErrorBoundary, {
...(isVue2
? {
Expand Down

0 comments on commit f6926d3

Please sign in to comment.