$ionicHistory.backView has incorrect state when go to previous state manually

前端 未结 2 1757
半阙折子戏
半阙折子戏 2020-12-18 06:29

I did a small experiment: http://codepen.io/hawkphil/pen/NqMomm?editors=101

Here is my state flow (click on the buttons): Home -> Fact1 -> Fact2 -> Fa

相关标签:
2条回答
  • 2020-12-18 07:09

    There are a lot of questions about history and navigation among the issues open on github.

    I guess the navigation is broken and needs to be fixed.

    $ionicHistory keeps track of the view pushing each visited view on a stack. Actually there are 2 arrays there:

    $ionicHistory.viewHistory().views
    

    and

    $ionicHistory.viewHistory().histories
    

    I guess the first one is the history of views for the current stack while the second considers all the histories.
    Different navigations can have different histories: tabs, sidemenu etc etc, and Ionic should remember each state when you switch from one history to the other.

    Reading through their documentation you can find this:

    Unlike a traditional browser environment, apps and webapps have parallel independent histories, such as with tabs. Should a user navigate few pages deep on one tab, and then switch to a new tab and back, the back button relates not to the previous tab, but to the previous pages visited within that tab.

    You can find the currentHistoryId here: $ionicHistory.currentHistoryId().

    I've changed your example a little bit displaying the 2 arrays when entering the view of the main controller:

    .controller('MainCtrl', function($scope, $rootScope, $timeout, $ionicHistory) {
          $scope.$on('$ionicView.enter', function(e) {
            var history = $ionicHistory.viewHistory();
            angular.forEach(history.views, function(view, index){
                console.log('views: ' + view.stateName);
            });
            angular.forEach(history.histories[$ionicHistory.currentHistoryId()].stack, function(view, index){
                console.log('history stack:' + view.stateName);
            });
        });
    })
    

    As you can see, the first array views keeps track of all the views you have visited.
    If you go back and forth in doesn't add elements if you are displaying a view you've previously visited.

    Each view has two properties: backViewId and forwardViewId. These 2 values seems to be part of the view when the elements are added to the collection. They don't change when you navigate.

    So, what happens is when you follow the sequence:

    Home -> Fact1 -> Fact2 -> Fact3 -> Fact2
    

    Ionic finds the view Fact2 in the collection, gets it's backViewId (which points to Fact1) and that's what it will use as a view to go back to.

    I didn't some debugging in the code and tried to force the back-view myself but things get messed up.

    I guess they've chosen this path cause when you're back to the root - home - the back button should be hidden. Things don't work as expected when you follow the sequence:

    Another thing I've noticed is the fact that sometimes views are added to this collection even if the element is already there.

    You can try the sequence:

    Home -> Fact1 -> Fact2 - Home (button)
    

    As you can see now the back button (in the header) tells you the back view is Fact2 and in fact the console shows the same:

    • views: tabs.home
    • views: tabs.fact1
    • views: tabs.fact2
    • views: tabs.home
    • history stack:tabs.home
    • history stack:tabs.fact1
    • history stack:tabs.fact2
    • history stack:tabs.home

    For some strange reason this time a new view has been added to the collection and the regular pattern has changed.

    There's a codepen here with some tests.

    0 讨论(0)
  • 2020-12-18 07:22

    My solution/workaround:

    Create an additional state to traverse to that references the same url, templateUrl, and controller.

    For example if I have:

    $stateProvider.state('fact2', { url: '/fact2/:factFilter', templateUrl: 'fact2.html', controller: 'Fact2Ctrl' })

    Then I also create a "fact2" duplicate with only a different state name

    $stateProvider.state('fact2_duplicate', { url: '/fact2/:factFilter', templateUrl: 'fact2.html', controller: 'Fact2Ctrl' })

    If I am receiving the funny transition behavior, I can call $state.go('fact2_duplicate') and the history will be more inline to what I am expecting.

    Hope this helps someone.

    0 讨论(0)
提交回复
热议问题