fix(vue): improve compatibility with route guards (#22371)

resolves #22344
This commit is contained in:
Liam DeBeasi
2020-10-22 11:03:58 -04:00
committed by GitHub
parent 561a4ac535
commit 31f9bc81d6
6 changed files with 69 additions and 8 deletions

View File

@ -1,7 +1,6 @@
import { import {
Router, Router,
RouteLocationNormalized, RouteLocationNormalized
NavigationGuardNext
} from 'vue-router'; } from 'vue-router';
import { createLocationHistory } from './locationHistory'; import { createLocationHistory } from './locationHistory';
import { generateId } from './utils'; import { generateId } from './utils';
@ -19,13 +18,20 @@ import { AnimationBuilder } from '@ionic/core';
export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) => { export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) => {
let currentNavigationInfo: NavigationInformation = { direction: undefined, action: undefined }; let currentNavigationInfo: NavigationInformation = { direction: undefined, action: undefined };
router.beforeEach((to: RouteLocationNormalized, _: RouteLocationNormalized, next: NavigationGuardNext) => { /**
* Ionic Vue should only react to navigation
* changes once they have been confirmed and should
* never affect the outcome of navigation (with the
* exception of going back or selecting a tab).
* As a result, we should do our work in afterEach
* which is fired once navigation is confirmed
* and any user guards have run.
*/
router.afterEach((to: RouteLocationNormalized, _: RouteLocationNormalized) => {
const { direction, action } = currentNavigationInfo; const { direction, action } = currentNavigationInfo;
handleHistoryChange(to, action, direction); handleHistoryChange(to, action, direction);
currentNavigationInfo = { direction: undefined, action: undefined }; currentNavigationInfo = { direction: undefined, action: undefined };
next();
}); });
const locationHistory = createLocationHistory(); const locationHistory = createLocationHistory();

View File

@ -0,0 +1,18 @@
import { loadingController } from '@ionic/vue';
import {
NavigationGuardNext,
RouteLocationNormalized
} from 'vue-router';
export const DelayGuard = async (_: RouteLocationNormalized, _x: RouteLocationNormalized, next: NavigationGuardNext) => {
const loading = await loadingController.create({
message: 'Waiting 500ms...',
duration: 500
});
await loading.present();
await loading.onDidDismiss();
next({ path: '/routing' });
}

View File

@ -1,12 +1,18 @@
import { createRouter, createWebHistory } from '@ionic/vue-router'; import { createRouter, createWebHistory } from '@ionic/vue-router';
import { RouteRecordRaw } from 'vue-router'; import { RouteRecordRaw } from 'vue-router';
import Home from '../views/Home.vue' import Home from '@/views/Home.vue'
import { DelayGuard } from '@/guards/Delay';
const routes: Array<RouteRecordRaw> = [ const routes: Array<RouteRecordRaw> = [
{ {
path: '/', path: '/',
component: Home component: Home
}, },
{
path: '/delayed-redirect',
beforeEnter: DelayGuard,
component: Home
},
{ {
path: '/lifecycle', path: '/lifecycle',
component: () => import('@/views/Lifecycle.vue') component: () => import('@/views/Lifecycle.vue')
@ -89,6 +95,9 @@ const routes: Array<RouteRecordRaw> = [
}, },
{ {
path: 'tab3', path: 'tab3',
beforeEnter: (to, from, next) => {
next({ path: '/tabs/tab1' });
},
component: () => import('@/views/Tab3.vue') component: () => import('@/views/Tab3.vue')
} }
] ]
@ -120,6 +129,6 @@ const routes: Array<RouteRecordRaw> = [
const router = createRouter({ const router = createRouter({
history: createWebHistory(process.env.BASE_URL), history: createWebHistory(process.env.BASE_URL),
routes routes
}) });
export default router export default router

View File

@ -44,6 +44,9 @@
<ion-item router-link="/lifecycle" id="lifecycle"> <ion-item router-link="/lifecycle" id="lifecycle">
<ion-label>Lifecycle</ion-label> <ion-label>Lifecycle</ion-label>
</ion-item> </ion-item>
<ion-item router-link="/delayed-redirect" id="delayed-redirect">
<ion-label>Delayed Redirect</ion-label>
</ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>

View File

@ -62,7 +62,23 @@ describe('Routing', () => {
cy.ionPageDoesNotExist('routingparameter'); cy.ionPageDoesNotExist('routingparameter');
cy.ionPageVisible('routing'); cy.ionPageVisible('routing');
}) });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22359
it('should work properly with async navigation guards', () => {
cy.visit('http://localhost:8080');
cy.get('#delayed-redirect').click();
cy.get('ion-loading').should('exist');
cy.ionPageVisible('routing');
cy.ionPageHidden('home');
cy.ionBackClick('routing');
cy.ionPageVisible('home');
cy.ionPageDoesNotExist('routing');
});
}); });
describe('Routing - Swipe to Go Back', () => { describe('Routing - Swipe to Go Back', () => {

View File

@ -113,6 +113,15 @@ describe('Tabs', () => {
cy.get('ion-tab-button#tab-button-tab2').click(); cy.get('ion-tab-button#tab-button-tab2').click();
cy.ionPageVisible('tab2'); cy.ionPageVisible('tab2');
}); });
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/22344
it('should show tab 1 when redirecting from tab 3', () => {
cy.visit('http://localhost:8080/tabs/tab3');
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab3');
cy.ionPageVisible('tabs');
});
}) })
describe('Tabs - Swipe to Go Back', () => { describe('Tabs - Swipe to Go Back', () => {