J'ai fait une petite expérience: http://codepen.io/hawkphil/pen/NqMomm?editors=101

Voici mon flux d'état (cliquez sur les boutons): Home -> Fact1 -> Fact2 -> Fact3 -> Fact2

À chaque changement d'état, j'affiche dans console.log pour $ionicHistory.backView Cependant, vous pouvez voir dans la ligne pen.js:64, des choses étranges se produisent. Le $ionicHistory.backView "pense" que je suis arrivé à app.fact2 à partir d'un bouton de retour, et il montre app.fact1 comme état précédent (ligne pen.js:53). C'est incorrect, non? Il devrait afficher app.fact3 comme état précédent car je suis arrivé à app.fact2 l'état MANUELLEMENT en cliquant sur le bouton. J'ai également montré la valeur de $timeout (ligne pen.js:59) juste au cas où elle serait lente. Mais c'est toujours incorrect.

pen.js:56 stateChangeSuccess
pen.js:64 State change from: tabs.home to: tabs.fact1
pen.js:52 $scope.$watch $ionicHistory.backView change detect. newVal:
pen.js:53 tabs.home
pen.js:58 $timeout after 2 sec $ionicHistory.backView().stateName
pen.js:59 tabs.home
pen.js:56 stateChangeSuccess
pen.js:64 State change from: tabs.fact1 to: tabs.fact2
pen.js:52 $scope.$watch $ionicHistory.backView change detect. newVal:
pen.js:53 tabs.fact1
pen.js:58 $timeout after 2 sec $ionicHistory.backView().stateName
pen.js:59 tabs.fact1
pen.js:56 stateChangeSuccess
pen.js:64 State change from: tabs.fact2 to: tabs.fact3
pen.js:52 $scope.$watch $ionicHistory.backView change detect. newVal:
pen.js:53 tabs.fact2
pen.js:58 $timeout after 2 sec $ionicHistory.backView().stateName
pen.js:59 tabs.fact2
pen.js:56 stateChangeSuccess
pen.js:64 State change from: tabs.fact3 to: tabs.fact2
pen.js:52 $scope.$watch $ionicHistory.backView change detect. newVal:
pen.js:53 tabs.fact1
pen.js:58 $timeout after 2 sec $ionicHistory.backView().stateName
pen.js:59 tabs.fact1

QUESTION

  1. Comment corriger ce comportement? Peut-être réécrire ce délégué ou le remplacer d'une manière ou d'une autre?

  2. Y at-il un travail autour? Comme je me fie au bon état précédent pour afficher / masquer quelque chose.

JS

angular.module('ionicApp', ['ionic'])

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('tabs', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html",
      controller: "MainCtrl"
    })
    .state('tabs.home', {
      url: "/home",
      views: {
        'home-tab': {
          templateUrl: "templates/home.html",
          controller: 'HomeTabCtrl'
        }
      }
    })
    .state('tabs.fact1', {
      url: "/fact1",
      views: {
        'home-tab': {
          templateUrl: "templates/fact1.html",
          controller: 'Fact1TabCtrl'
        }
      }
    })
    .state('tabs.fact2', {
      url: "/fact2",
      views: {
        'home-tab': {
          templateUrl: "templates/fact2.html",
          controller: 'Fact2TabCtrl'
        }
      }
    })
    .state('tabs.fact3', {
      url: "/fact3",
      views: {
        'home-tab': {
          templateUrl: "templates/fact3.html",
          controller: 'Fact3TabCtrl'
        }
      }
    })
    .state('tabs.about', {
      url: "/about",
      views: {
        'about-tab': {
          templateUrl: "templates/about.html"
        }
      }
    })
    .state('tabs.navstack', {
      url: "/navstack",
      views: {
        'about-tab': {
          templateUrl: "templates/nav-stack.html"
        }
      }
    });


   $urlRouterProvider.otherwise("/tab/home");

})

.controller('MainCtrl', function($scope, $rootScope, $timeout, $ionicHistory) {
    $scope.$watch(function() {
    return $ionicHistory.backView() ? $ionicHistory.backView().stateName : null;
  }, function (newVal, oldVal) {
    console.log('$scope.$watch $ionicHistory.backView change detect. newVal:');
    console.log(newVal);
  });

    $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ 
    console.log('stateChangeSuccess');

    $timeout(function(){ 
      console.log('$timeout after 2 sec $ionicHistory.backView().stateName');
      console.log($ionicHistory.backView().stateName);
    }, 2000);
    });
})

.controller('HomeTabCtrl', function($scope, $rootScope) {
  // console.log('Home');

  $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ 
    console.log('State change from: ' + fromState.name + ' to: ' + toState.name);
  });
})

.controller('Fact1TabCtrl', function($scope) {
  // console.log('Fact1');
})

.controller('Fact2TabCtrl', function($scope) {
  // console.log('Fact2');
})

.controller('Fact3TabCtrl', function($scope) {
  // console.log('Fact3');
});

HTML

<html ng-app="ionicApp">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

  <title>Navigation Example</title>

  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>

<body>

  <ion-nav-bar class="bar-positive">
    <ion-nav-back-button class="button-icon ion-arrow-left-c">
    </ion-nav-back-button>
  </ion-nav-bar>

  <ion-nav-view></ion-nav-view>


  <script id="templates/tabs.html" type="text/ng-template">
    <ion-tabs class="tabs-icon-top tabs-positive">

      <ion-tab title="Home" icon="ion-home" href="#/tab/home">
        <ion-nav-view name="home-tab"></ion-nav-view>
      </ion-tab>

      <ion-tab title="About" icon="ion-ios-football" href="#/tab/about">
        <ion-nav-view name="about-tab"></ion-nav-view>
      </ion-tab>

      </ion-tab>

    </ion-tabs>
  </script>

  <script id="templates/home.html" type="text/ng-template">
    <ion-view view-title="Home">
      <ion-content class="padding">
        <p>
          <a class="button icon ion-home" href="#/tab/home"> Home</a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact1">
            Fact1
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact2">
            Fact2
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact3">
            Fact3
          </a>
        </p>
      </ion-content>
    </ion-view>
  </script>

  <script id="templates/fact1.html" type="text/ng-template">
    <ion-view view-title="Fact1">
      <ion-content class="padding">
        <p>
          <a class="button icon ion-home" href="#/tab/home"> Home</a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact1">
            Fact1
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact2">
            Fact2
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact3">
            Fact3
          </a>
        </p>
      </ion-content>
    </ion-view>
  </script>

  <script id="templates/fact2.html" type="text/ng-template">
    <ion-view view-title="Fact2">
      <ion-content class="padding">
        <p>
          <a class="button icon ion-home" href="#/tab/home"> Home</a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact1">
            Fact1
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact2">
            Fact2
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact3">
            Fact3
          </a>
        </p>
      </ion-content>
    </ion-view>
  </script>

  <script id="templates/fact3.html" type="text/ng-template">
    <ion-view view-title="Fact3">
      <ion-content class="padding">
        <p>
          <a class="button icon ion-home" href="#/tab/home"> Home</a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact1">
            Fact1
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact2">
            Fact2
          </a>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/fact3">
            Fact3
          </a>
        </p>
      </ion-content>
    </ion-view>
  </script>

  <script id="templates/about.html" type="text/ng-template">
    <ion-view view-title="About">
      <ion-content class="padding">
        <h3>Create hybrid mobile apps with the web technologies you love.</h3>
        <p>Free and open source, Ionic offers a library of mobile-optimized HTML, CSS and JS components for building highly interactive apps.</p>
        <p>Built with Sass and optimized for AngularJS.</p>
        <p>
          <a class="button icon icon-right ion-chevron-right" href="#/tab/navstack">Tabs Nav Stack</a>
        </p>
      </ion-content>
    </ion-view>
  </script>

  <script id="templates/nav-stack.html" type="text/ng-template">
    <ion-view view-title="Tab Nav Stack">
      <ion-content class="padding">
        <p><img src="http://ionicframework.com/img/diagrams/tabs-nav-stack.png" style="width:100%"></p>
      </ion-content>
    </ion-view>
  </script>

</body>

</html>
5
HP. 12 juil. 2015 à 08:10

2 réponses

Meilleure réponse

Il y a beaucoup de questions sur l'historique et la navigation parmi les problèmes ouverts sur github.

Je suppose que la navigation est interrompue et doit être corrigée.

$ionicHistory garde une trace de la vue poussant chaque vue visitée sur une pile. En fait, il y a 2 tableaux ici:

$ionicHistory.viewHistory().views

Et

$ionicHistory.viewHistory().histories

Je suppose que le premier est l'historique des vues de la pile actuelle tandis que le second considère toutes les histoires.
Différentes navigations peuvent avoir des historiques différents: onglets, sidemenu, etc., et Ionic devrait se souvenir de chaque état lorsque vous passez d'un historique à l'autre.

En lisant leur documentation, vous pouvez trouver ceci:

Contrairement à un environnement de navigateur traditionnel, les applications et les applications Web ont des historiques indépendants parallèles, comme avec les onglets. Si un utilisateur parcourt quelques pages de profondeur sur un onglet, puis passe à un nouvel onglet et retourne, le bouton de retour ne se rapporte pas à l'onglet précédent, mais aux pages précédentes visitées dans cet onglet.

Vous pouvez trouver le currentHistoryId ici: $ionicHistory.currentHistoryId().

J'ai un peu changé votre exemple en affichant les 2 tableaux en entrant dans la vue du contrôleur principal:

.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);
        });
    });
})

Comme vous pouvez le voir, le premier tableau vues garde une trace de toutes les vues que vous avez visitées.
Si vous faites des allers-retours dans n'ajoute pas d'éléments si vous affichez une vue que vous avez déjà visitée.

Chaque vue a deux propriétés: backViewId et forwardViewId . Ces 2 valeurs semblent faire partie de la vue lorsque les éléments sont ajoutés à la collection. Ils ne changent pas lorsque vous naviguez.

Donc, ce qui se passe, c'est lorsque vous suivez la séquence:

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

Ionic trouve la vue Fact2 dans la collection, la récupère backViewId (qui pointe vers Fact1) et c'est ce qu'elle utilisera comme vue pour revenir.

Je n'ai pas fait de débogage dans le code et j'ai essayé de forcer la vue arrière moi-même, mais les choses se gâtent.

Je suppose qu'ils ont choisi ce chemin car lorsque vous êtes de retour à la racine - à la maison - le bouton de retour devrait être caché. Les choses ne fonctionnent pas comme prévu lorsque vous suivez la séquence:

Une autre chose que j'ai remarquée est le fait que parfois des vues sont ajoutées à cette collection même si l'élément est déjà là.

Vous pouvez essayer la séquence:

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

Comme vous pouvez le voir maintenant, le bouton de retour (dans l'en-tête) vous indique que la vue arrière est Fact2 et en fait la console affiche la même chose:

  • vues: tabs.home
  • vues: tabs.fact1
  • vues: tabs.fact2
  • vues: tabs.home
  • pile d'historique: tabs.home
  • pile d'historique: tabs.fact1
  • pile d'historique: tabs.fact2
  • pile d'historique: tabs.home

Pour une raison étrange, cette fois, une nouvelle vue a été ajoutée à la collection et le modèle régulier a changé.

Il y a un codepen ici avec quelques tests.

11
LeftyX 13 juil. 2015 à 13:02

Ma solution / solution de contournement:

Créez un état supplémentaire à parcourir pour faire référence à la même URL, templateUrl et contrôleur.

Par exemple si j'ai:

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

Ensuite, je crée également un duplicata "fact2" avec seulement un nom d'état différent

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

Si je reçois le comportement de transition amusant, je peux appeler $state.go('fact2_duplicate') et l'historique sera plus en ligne avec ce que j'attends.

J'espère que cela aide quelqu'un.

0
aero 16 juil. 2016 à 16:21