Skip to content

Commit

Permalink
fix(vue): tabs no longer get unmounted when navigating back to a tabs…
Browse files Browse the repository at this point in the history
… context (#24337)

resolves #24332

Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
  • Loading branch information
sean-perkins and liamdebeasi committed Dec 15, 2021
1 parent 9c9e28c commit 4aab72b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
28 changes: 27 additions & 1 deletion packages/vue/src/components/IonRouterOutlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import { AnimationBuilder, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_W
import { matchedRouteKey, routeLocationKey, useRoute } from 'vue-router';
import { fireLifecycle, generateId, getConfig } from '../utils';

const isViewVisible = (enteringEl: HTMLElement) => {
return !enteringEl.classList.contains('ion-page-hidden') && !enteringEl.classList.contains('ion-page-invisible');
}

let viewDepthKey: InjectionKey<0> = Symbol(0);
export const IonRouterOutlet = defineComponent({
name: 'IonRouterOutlet',
Expand Down Expand Up @@ -230,13 +234,35 @@ export const IonRouterOutlet = defineComponent({
See https://ionicframework.com/docs/vue/navigation#ionpage for more information.`);
}

if (enteringViewItem === leavingViewItem) return;

if (!leavingViewItem && prevRouteLastPathname) {
leavingViewItem = viewStacks.findViewItemByPathname(prevRouteLastPathname, id, usingDeprecatedRouteSetup);
}

/**
* If the entering view is already
* visible, then no transition is needed.
* This is most common when navigating
* from a tabs page to a non-tabs page
* and then back to the tabs page.
* Even when the tabs context navigated away,
* the inner tabs page was still active.
* This also avoids an issue where
* the previous tabs page is incorrectly
* unmounted since it would automatically
* unmount the previous view.
*
* This should also only apply to entering and
* leaving items in the same router outlet (i.e.
* Tab1 and Tab2), otherwise this will
* return early for swipe to go back when
* going from a non-tabs page to a tabs page.
*/
if (isViewVisible(enteringEl) && leavingViewItem !== undefined && !isViewVisible(leavingViewItem.ionPageElement)) {
return;
}

fireLifecycle(enteringViewItem.vueComponent, enteringViewItem.vueComponentRef, LIFECYCLE_WILL_ENTER);

if (leavingViewItem && enteringViewItem !== leavingViewItem) {
Expand Down
29 changes: 28 additions & 1 deletion packages/vue/test-app/tests/e2e/specs/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ describe('Tabs', () => {
cy.url().should('include', '/tabs/tab1/child-one?key=value');
});

// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23699
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24353
it('should handle clicking tab multiple times without query string', () => {
cy.visit('http://localhost:8080/tabs/tab1');

Expand All @@ -329,6 +329,33 @@ describe('Tabs', () => {
cy.ionPageVisible('tab2');
cy.ionPageHidden('tab1');
});

// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24332
it('should not unmount tab 1 when leaving tabs context', () => {
cy.visit('http://localhost:8080/tabs');
cy.ionPageVisible('tab1');

// Dynamically add tab 4 because tab 3 redirects to tab 1
cy.get('#add-tab').click();

cy.get('ion-tab-button#tab-button-tab4').click();
cy.ionPageHidden('tab1');
cy.ionPageVisible('tab4');

cy.get('ion-tab-button#tab-button-tab2').click();
cy.ionPageHidden('tab4');
cy.ionPageVisible('tab2');

cy.get('[data-pageid="tab2"] #routing').click();
cy.ionPageVisible('routing');
cy.ionPageHidden('tabs');

cy.ionBackClick('routing');
cy.ionPageDoesNotExist('routing');
cy.ionPageVisible('tabs');
cy.ionPageVisible('tab2');
cy.ionPageHidden('tab1');
});
})

describe('Tabs - Swipe to Go Back', () => {
Expand Down

0 comments on commit 4aab72b

Please sign in to comment.