mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
fix(vue): ionic lifecycle hooks now run when using vue 3.2 setup syntax (#24253)
resolves #23824 Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
This commit is contained in:
@ -80,6 +80,12 @@ const injectHook = (lifecycleType: LifecycleHooks, hook: Function, component: Co
|
|||||||
// Add to public instance so it is accessible to IonRouterOutlet
|
// Add to public instance so it is accessible to IonRouterOutlet
|
||||||
const target = component as any;
|
const target = component as any;
|
||||||
const hooks = target.proxy[lifecycleType] || (target.proxy[lifecycleType] = []);
|
const hooks = target.proxy[lifecycleType] || (target.proxy[lifecycleType] = []);
|
||||||
|
/**
|
||||||
|
* Define property on public instances using `setup` syntax in Vue 3.x
|
||||||
|
*/
|
||||||
|
if (target.exposed) {
|
||||||
|
target.exposed[lifecycleType] = hooks;
|
||||||
|
}
|
||||||
const wrappedHook = (...args: unknown[]) => {
|
const wrappedHook = (...args: unknown[]) => {
|
||||||
if (target.isUnmounted) {
|
if (target.isUnmounted) {
|
||||||
return;
|
return;
|
||||||
|
@ -17,6 +17,10 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
path: '/lifecycle',
|
path: '/lifecycle',
|
||||||
component: () => import('@/views/Lifecycle.vue')
|
component: () => import('@/views/Lifecycle.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/lifecycle-setup',
|
||||||
|
component: () => import('@/views/LifecycleSetup.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/overlays',
|
path: '/overlays',
|
||||||
name: 'Overlays',
|
name: 'Overlays',
|
||||||
|
@ -47,6 +47,9 @@
|
|||||||
<ion-item button router-link="/lifecycle" id="lifecycle">
|
<ion-item button router-link="/lifecycle" id="lifecycle">
|
||||||
<ion-label>Lifecycle</ion-label>
|
<ion-label>Lifecycle</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ion-item button router-link="/lifecycle-setup" id="lifecycle-setup">
|
||||||
|
<ion-label>Lifecycle (Setup)</ion-label>
|
||||||
|
</ion-item>
|
||||||
<ion-item button router-link="/delayed-redirect" id="delayed-redirect">
|
<ion-item button router-link="/delayed-redirect" id="delayed-redirect">
|
||||||
<ion-label>Delayed Redirect</ion-label>
|
<ion-label>Delayed Redirect</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
56
packages/vue/test-app/src/views/LifecycleSetup.vue
Normal file
56
packages/vue/test-app/src/views/LifecycleSetup.vue
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<ion-page data-pageid="lifecycle-setup">
|
||||||
|
<ion-header :translucent="true">
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-buttons>
|
||||||
|
<ion-back-button></ion-back-button>
|
||||||
|
</ion-buttons>
|
||||||
|
<ion-title>Lifecycle (Setup)</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content :fullscreen="true">
|
||||||
|
<ion-header collapse="condense">
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title size="large">Lifecycle (Setup)</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<div class="ion-padding">
|
||||||
|
onIonViewWillEnter: <div id="onWillEnter">{{ onWillEnter }}</div><br />
|
||||||
|
onIonViewDidEnter: <div id="onDidEnter">{{ onDidEnter }}</div><br />
|
||||||
|
onIonViewWillLeave: <div id="onWillLeave">{{ onWillLeave }}</div><br />
|
||||||
|
onIonViewDidLeave: <div id="onDidLeave">{{ onDidLeave }}</div><br />
|
||||||
|
|
||||||
|
<ion-button router-link="/navigation" id="lifecycle-navigation">Go to another page</ion-button>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {
|
||||||
|
IonButton,
|
||||||
|
IonBackButton,
|
||||||
|
IonButtons,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
|
IonPage,
|
||||||
|
IonTitle,
|
||||||
|
IonToolbar,
|
||||||
|
onIonViewWillEnter,
|
||||||
|
onIonViewDidEnter,
|
||||||
|
onIonViewWillLeave,
|
||||||
|
onIonViewDidLeave
|
||||||
|
} from '@ionic/vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
const onWillEnter = ref(0);
|
||||||
|
const onDidEnter = ref(0);
|
||||||
|
const onWillLeave = ref(0);
|
||||||
|
const onDidLeave = ref(0);
|
||||||
|
|
||||||
|
onIonViewWillEnter(() => onWillEnter.value += 1);
|
||||||
|
onIonViewDidEnter(() => onDidEnter.value += 1);
|
||||||
|
onIonViewWillLeave(() => onWillLeave.value += 1);
|
||||||
|
onIonViewDidLeave(() => onDidLeave.value += 1);
|
||||||
|
</script>
|
@ -55,14 +55,62 @@ describe('Lifecycle', () => {
|
|||||||
onIonViewDidLeave: 0
|
onIonViewDidLeave: 0
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should fire lifecycle events when navigating to and from a page - setup', () => {
|
||||||
|
cy.visit('http://localhost:8080');
|
||||||
|
cy.get('#lifecycle-setup').click();
|
||||||
|
|
||||||
|
testLifecycle('lifecycle-setup', {
|
||||||
|
onIonViewWillEnter: 1,
|
||||||
|
onIonViewDidEnter: 1,
|
||||||
|
onIonViewWillLeave: 0,
|
||||||
|
onIonViewDidLeave: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('#lifecycle-navigation').click();
|
||||||
|
|
||||||
|
testLifecycle('lifecycle-setup', {
|
||||||
|
onIonViewWillEnter: 1,
|
||||||
|
onIonViewDidEnter: 1,
|
||||||
|
onIonViewWillLeave: 1,
|
||||||
|
onIonViewDidLeave: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.ionBackClick('navigation');
|
||||||
|
|
||||||
|
testLifecycle('lifecycle-setup', {
|
||||||
|
onIonViewWillEnter: 2,
|
||||||
|
onIonViewDidEnter: 2,
|
||||||
|
onIonViewWillLeave: 1,
|
||||||
|
onIonViewDidLeave: 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fire lifecycle events when landed on directly - setup', () => {
|
||||||
|
cy.visit('http://localhost:8080/lifecycle-setup');
|
||||||
|
|
||||||
|
testLifecycle('lifecycle-setup', {
|
||||||
|
onIonViewWillEnter: 1,
|
||||||
|
onIonViewDidEnter: 1,
|
||||||
|
onIonViewWillLeave: 0,
|
||||||
|
onIonViewDidLeave: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
const testLifecycle = (selector, expected = {}) => {
|
const testLifecycle = (selector, expected = {}) => {
|
||||||
cy.get(`[data-pageid=${selector}] #willEnter`).should('have.text', expected.ionViewWillEnter);
|
if (expected.ionViewWillEnter) {
|
||||||
cy.get(`[data-pageid=${selector}] #didEnter`).should('have.text', expected.ionViewDidEnter);
|
cy.get(`[data-pageid=${selector}] #willEnter`).should('have.text', expected.ionViewWillEnter);
|
||||||
cy.get(`[data-pageid=${selector}] #willLeave`).should('have.text', expected.ionViewWillLeave);
|
}
|
||||||
cy.get(`[data-pageid=${selector}] #didLeave`).should('have.text', expected.ionViewDidLeave);
|
if (expected.ionViewDidEnter) {
|
||||||
|
cy.get(`[data-pageid=${selector}] #didEnter`).should('have.text', expected.ionViewDidEnter);
|
||||||
|
}
|
||||||
|
if (expected.ionViewWillLeave) {
|
||||||
|
cy.get(`[data-pageid=${selector}] #willLeave`).should('have.text', expected.ionViewWillLeave);
|
||||||
|
}
|
||||||
|
if (expected.ionViewDidLeave) {
|
||||||
|
cy.get(`[data-pageid=${selector}] #didLeave`).should('have.text', expected.ionViewDidLeave);
|
||||||
|
}
|
||||||
cy.get(`[data-pageid=${selector}] #onWillEnter`).should('have.text', expected.onIonViewWillEnter);
|
cy.get(`[data-pageid=${selector}] #onWillEnter`).should('have.text', expected.onIonViewWillEnter);
|
||||||
cy.get(`[data-pageid=${selector}] #onDidEnter`).should('have.text', expected.onIonViewDidEnter);
|
cy.get(`[data-pageid=${selector}] #onDidEnter`).should('have.text', expected.onIonViewDidEnter);
|
||||||
cy.get(`[data-pageid=${selector}] #onWillLeave`).should('have.text', expected.onIonViewWillLeave);
|
cy.get(`[data-pageid=${selector}] #onWillLeave`).should('have.text', expected.onIonViewWillLeave);
|
||||||
|
Reference in New Issue
Block a user