fix(vue): navigating between parameterized pages now results in page transition (#23525)

resolves #22662
This commit is contained in:
Liam DeBeasi
2021-06-30 10:11:06 -04:00
committed by GitHub
parent 6ca17805b8
commit e30b17c5bb
9 changed files with 64 additions and 97 deletions

View File

@ -23,31 +23,7 @@ export const createViewStacks = (router: Router) => {
} }
const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => { const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
let viewItem = findViewItemByPath(routeInfo.pathname, outletId, false); return findViewItemByPath(routeInfo.pathname, outletId, false);
/**
* Given a route such as /path/:id,
* going from /page/1 to /home
* to /page/2 will cause the same
* view item from /page/1 to match
* for /page/2 so we need to make
* sure any params get updated.
* Not normally an issue for accessing
* the params via useRouter from vue-router,
* but when passing params as props not doing
* this would cause the old props to show up.
*/
if (viewItem && viewItem.params !== routeInfo.params) {
/**
* Clear the props function result
* as the value may have changed due
* to different props.
*/
delete viewItem.vueComponentData.propsFunctionResult;
viewItem.params = routeInfo.params;
}
return viewItem;
} }
const findLeavingViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number, mustBeIonRoute: boolean = true) => { const findLeavingViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number, mustBeIonRoute: boolean = true) => {
@ -81,6 +57,20 @@ export const createViewStacks = (router: Router) => {
const findMatchedRoute = resolvedPath.matched.find((matchedRoute: RouteLocationMatched) => matchedRoute === viewItem.matchedRoute); const findMatchedRoute = resolvedPath.matched.find((matchedRoute: RouteLocationMatched) => matchedRoute === viewItem.matchedRoute);
if (findMatchedRoute) { if (findMatchedRoute) {
/**
* /page/1 and /page/2 should not match
* to the same view item otherwise there will
* be not page transition and we will need to
* explicitly clear out parameters from page 1
* so the page 2 params are properly passed
* to the developer's app.
*/
const hasParameter = findMatchedRoute.path.includes(':');
if (hasParameter && path !== viewItem.pathname) {
return false;
}
return viewItem; return viewItem;
} }

View File

@ -90,12 +90,9 @@ const routes: Array<RouteRecordRaw> = [
component: () => import('@/views/Tab1.vue'), component: () => import('@/views/Tab1.vue'),
}, },
{ {
path: 'tab1/child-one', path: 'tab1/:id',
component: () => import('@/views/Tab1ChildOne.vue') component: () => import('@/views/Tab1Parameter.vue'),
}, props: true
{
path: 'tab1/child-two',
component: () => import('@/views/Tab1ChildTwo.vue')
}, },
{ {
path: 'tab2', path: 'tab2',

View File

@ -1,5 +1,5 @@
<template> <template>
<ion-page data-pageid="routingparameter"> <ion-page :data-pageid="'routingparameter-' + $props.id">
<ion-header :translucent="true"> <ion-header :translucent="true">
<ion-toolbar> <ion-toolbar>
<ion-buttons> <ion-buttons>

View File

@ -17,7 +17,7 @@
<ExploreContainer name="Tab 1 page" /> <ExploreContainer name="Tab 1 page" />
<ion-item button router-link="/tabs/tab1/child-one" id="child-one"> <ion-item button router-link="/tabs/tab1/childone" id="child-one">
<ion-label>Go to Tab 1 Child 1</ion-label> <ion-label>Go to Tab 1 Child 1</ion-label>
</ion-item> </ion-item>
<ion-item button router-link="/nested" id="nested"> <ion-item button router-link="/nested" id="nested">

View File

@ -1,44 +0,0 @@
<template>
<ion-page data-pageid="tab1childtwo">
<ion-header>
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Tab 1 Child 2</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Tab 1 Child 2</ion-title>
</ion-toolbar>
</ion-header>
</ion-content>
</ion-page>
</template>
<script>
import {
IonButtons,
IonBackButton,
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent
} from '@ionic/vue';
export default {
components: {
IonButtons,
IonBackButton,
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent
}
}
</script>

View File

@ -1,21 +1,25 @@
<template> <template>
<ion-page data-pageid="tab1childone"> <ion-page :data-pageid="'tab1' + $props.id">
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-buttons> <ion-buttons>
<ion-back-button></ion-back-button> <ion-back-button></ion-back-button>
</ion-buttons> </ion-buttons>
<ion-title>Tab 1 Child 1</ion-title> <ion-title>Tab 1 Child {{ $props.id }}</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content :fullscreen="true"> <ion-content :fullscreen="true">
<ion-header collapse="condense"> <ion-header collapse="condense">
<ion-toolbar> <ion-toolbar>
<ion-title size="large">Tab 1 Child 1</ion-title> <ion-title size="large">Tab 1 Child {{ $props.id }}</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-item router-link="child-two" id="child-two"> <ion-item router-link="childone" id="child-one">
<ion-label>Tab 1 Child 1</ion-label>
</ion-item>
<ion-item router-link="childtwo" id="child-two">
<ion-label>Tab 1 Child 2</ion-label> <ion-label>Tab 1 Child 2</ion-label>
</ion-item> </ion-item>
@ -37,6 +41,7 @@ import {
} from '@ionic/vue'; } from '@ionic/vue';
export default { export default {
props: { id: String },
components: { components: {
IonButtons, IonButtons,
IonBackButton, IonBackButton,

View File

@ -53,15 +53,15 @@ describe('Routing', () => {
cy.visit('http://localhost:8080/routing'); cy.visit('http://localhost:8080/routing');
cy.get('#parameter-abc').click(); cy.get('#parameter-abc').click();
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-abc');
cy.get('[data-pageid=routingparameter] #parameter-value').should('have.text', 'abc'); cy.get('[data-pageid=routingparameter-abc] #parameter-value').should('have.text', 'abc');
cy.ionBackClick('routingparameter'); cy.ionBackClick('routingparameter-abc');
cy.ionPageDoesNotExist('routingparameter'); cy.ionPageDoesNotExist('routingparameter-abc');
cy.get('#parameter-xyz').click(); cy.get('#parameter-xyz').click();
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-xyz');
cy.get('[data-pageid=routingparameter] #parameter-value').should('have.text', 'xyz'); cy.get('[data-pageid=routingparameter-xyz] #parameter-value').should('have.text', 'xyz');
}); });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22359 // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22359
@ -69,7 +69,7 @@ describe('Routing', () => {
cy.visit('http://localhost:8080/routing'); cy.visit('http://localhost:8080/routing');
cy.get('#parameter-abc').click(); cy.get('#parameter-abc').click();
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-abc');
cy.get('#parameter-view').click(); cy.get('#parameter-view').click();
@ -149,32 +149,32 @@ describe('Routing', () => {
}); });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22658 // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22658
it('should select correct leaving view when navigating between paramter urls', () => { it('should select correct leaving view when navigating between parameter urls', () => {
cy.visit('http://localhost:8080'); cy.visit('http://localhost:8080');
cy.routerPush('/routing/123'); cy.routerPush('/routing/123');
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-123');
cy.ionPageHidden('home'); cy.ionPageHidden('home');
cy.routerPush('/routing/456'); cy.routerPush('/routing/456');
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-456');
cy.ionPageHidden('home'); cy.ionPageHidden('home');
cy.routerPush('/navigation'); cy.routerPush('/navigation');
cy.ionPageVisible('navigation'); cy.ionPageVisible('navigation');
cy.ionPageHidden('routingparameter'); cy.ionPageHidden('routingparameter-456');
cy.routerPush('/routing/789'); cy.routerPush('/routing/789');
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-789');
cy.ionPageHidden('home'); cy.ionPageHidden('home');
cy.routerPush('/routing/000'); cy.routerPush('/routing/000');
cy.ionPageVisible('routingparameter'); cy.ionPageVisible('routingparameter-000');
cy.ionPageHidden('home'); cy.ionPageHidden('home');
cy.routerPush('/navigation'); cy.routerPush('/navigation');
cy.ionPageVisible('navigation'); cy.ionPageVisible('navigation');
cy.ionPageHidden('routingparameter'); cy.ionPageHidden('routingparameter-000');
}); });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22528 // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22528
@ -191,6 +191,24 @@ describe('Routing', () => {
cy.ionBackButtonHidden('home'); cy.ionBackButtonHidden('home');
}); });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22662
it('should push a new instance of a parameterized page so there is a transition', () => {
cy.visit('http://localhost:8080');
cy.routerPush('/routing/123');
cy.ionPageVisible('routingparameter-123');
cy.ionPageHidden('home');
cy.routerPush('/routing/456');
cy.ionPageVisible('routingparameter-456');
cy.ionPageHidden('routingparameter-123');
cy.ionBackClick('routingparameter-456');
cy.ionPageVisible('routingparameter-123')
cy.ionPageDoesNotExist('routingparameter-456');
})
}); });
describe('Routing - Swipe to Go Back', () => { describe('Routing - Swipe to Go Back', () => {

View File

@ -50,7 +50,6 @@ Cypress.Commands.add('ionPageVisible', (pageId) => {
Cypress.Commands.add('ionPageHidden', (pageId) => { Cypress.Commands.add('ionPageHidden', (pageId) => {
cy.get(`div.ion-page[data-pageid=${pageId}]`) cy.get(`div.ion-page[data-pageid=${pageId}]`)
.should('have.class', 'ion-page-hidden') .should('have.class', 'ion-page-hidden')
.should('have.length', 1)
}) })
Cypress.Commands.add('ionBackClick', (pageId) => { Cypress.Commands.add('ionBackClick', (pageId) => {

View File

@ -392,6 +392,8 @@ describe('Routing', () => {
router.push('/page/2'); router.push('/page/2');
await waitForRouter(); await waitForRouter();
expect(page.props()).toEqual({ id: '2' }); const pageAgain = wrapper.findAllComponents(Page);
expect(pageAgain[0].props()).toEqual({ id: '1' });
expect(pageAgain[1].props()).toEqual({ id: '2' });
}); });
}); });