fix(vue): tapping the active tab button now correctly resets the tab stack (#24935)

resolves #24934
This commit is contained in:
Liam DeBeasi
2022-03-14 14:44:47 -04:00
committed by GitHub
parent d46e1e8506
commit 4534c8bc0b
4 changed files with 92 additions and 13 deletions

View File

@ -92,16 +92,39 @@ export const createLocationHistory = () => {
* and every entry that appears after it. * and every entry that appears after it.
*/ */
const clearHistory = (routeInfo?: RouteInfo) => { const clearHistory = (routeInfo?: RouteInfo) => {
Object.keys(tabsHistory).forEach(key => {
tabsHistory[key] = [];
});
if (routeInfo) { if (routeInfo) {
/**
* If there is no route index in locationHistory
* then there will not be any route index in
* tabs either.
*/
const existingRouteIndex = locationHistory.findIndex(r => r.position === routeInfo.position); const existingRouteIndex = locationHistory.findIndex(r => r.position === routeInfo.position);
if (existingRouteIndex === -1) return; if (existingRouteIndex === -1) return;
locationHistory.splice(existingRouteIndex); locationHistory.splice(existingRouteIndex);
/**
* We also need to search the current tab
* to correctly reset the individual tab
* stack. We should not clear the entire
* tab stack as that means we will lose
* a reference to the root tab route.
*/
const { tab } = routeInfo;
const tabHistory = tabsHistory[tab];
if (tab && tabHistory) {
const existingTabRouteIndex = tabHistory.findIndex(r => r.position === routeInfo.position);
if (existingTabRouteIndex === -1) return;
tabsHistory[tab].splice(existingTabRouteIndex);
}
} else { } else {
Object.keys(tabsHistory).forEach(key => {
tabsHistory[key] = [];
});
locationHistory.length = 0; locationHistory.length = 0;
} }
} }

View File

@ -409,13 +409,22 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
router.push(routerLink); router.push(routerLink);
} }
const resetTab = (tab: string, originalHref: string) => { const resetTab = (tab: string) => {
/**
* Resetting the tab should go back
* to the initial view in the tab stack.
* It should not push a new instance of the
* root tab page onto the stack.
*
* To do this, we get the initial view in the
* tab stack and subtract the position of that
* entry from our current position. From there
* we call router.go() to move us back the
* appropriate number of positions.
*/
const routeInfo = locationHistory.getFirstRouteInfoForTab(tab); const routeInfo = locationHistory.getFirstRouteInfoForTab(tab);
if (routeInfo) { if (routeInfo) {
const newRouteInfo = { ...routeInfo }; router.go(routeInfo.position - currentHistoryPosition);
newRouteInfo.pathname = originalHref;
incomingRouteParams = { ...newRouteInfo, routerAction: 'pop', routerDirection: 'back' };
router.push({ path: newRouteInfo.pathname, query: parseQuery(newRouteInfo.search) });
} }
} }

View File

@ -47,7 +47,7 @@ export const IonTabButton = /*@__PURE__*/ defineComponent({
*/ */
if (prevActiveTab === tab) { if (prevActiveTab === tab) {
if (originalHref !== currentHref) { if (originalHref !== currentHref) {
ionRouter.resetTab(tab, originalHref); ionRouter.resetTab(tab);
} }
} else { } else {
ionRouter.changeTab(tab, currentHref) ionRouter.changeTab(tab, currentHref)

View File

@ -51,21 +51,68 @@ describe('Tabs', () => {
cy.ionPageHidden('tab1'); cy.ionPageHidden('tab1');
}); });
it('should return to tab root when clicking tab button', () => { it('should return to tab root when clicking tab button after going back', () => {
cy.visit('http://localhost:8080/tabs') cy.visit('http://localhost:8080/tabs')
cy.get('#child-one').click(); cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');
cy.get('#child-two').click(); cy.get('#child-two').click();
cy.ionPageHidden('tab1childone');
cy.ionPageVisible('tab1childtwo');
cy.get('ion-tab-button#tab-button-tab1').click(); cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1'); cy.ionPageVisible('tab1');
// TODO this page is not removed cy.ionPageDoesNotExist('tab1childone');
//cy.ionPageDoesNotExist('tab1childone');
cy.ionPageDoesNotExist('tab1childtwo'); cy.ionPageDoesNotExist('tab1childtwo');
}) })
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24934
it('should return to tab root when clicking tab button', () => {
cy.visit('http://localhost:8080/tabs')
cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');
cy.get('#child-two').click();
cy.ionPageHidden('tab1childone');
cy.ionPageVisible('tab1childtwo');
cy.ionBackClick('tab1childtwo');
cy.ionPageVisible('tab1childone');
cy.ionPageDoesNotExist('tab1childtwo');
cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');
})
// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24934
it('should return to tab root after replacing history', () => {
cy.visit('http://localhost:8080/tabs')
cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');
cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');
cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');
cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');
})
it('should be able to create and destroy tabs', () => { it('should be able to create and destroy tabs', () => {
cy.visit('http://localhost:8080') cy.visit('http://localhost:8080')