手动转到上一个状态时,$ ionicHistory.backView的状态不正确

时间:2015-07-12 05:10:38

标签: javascript angularjs ionic-framework angular-ui-router

我做了一个小实验:http://codepen.io/hawkphil/pen/NqMomm?editors=101

这是我的状态流程(点击按钮):Home -> Fact1 -> Fact2 -> Fact3 -> Fact2

每次状态更改时,我都会在console.log中显示$ionicHistory.backView 但是,您可以在pen.js:64行中看到奇怪的事情发生。 $ionicHistory.backView"认为"我从后退按钮前往app.fact2,并将app.fact1显示为之前的状态(行pen.js:53)。这是不对的,对吗?它应该显示app.fact3作为之前的状态,因为我通过单击按钮来app.fact2状态手动。我还显示了$timeout(行pen.js:59)的值,以防它变慢。但它仍然是不正确的。

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

问题

  1. 如何纠正此行为?也许重写这个委托或以某种方式覆盖它?

  2. 有解决方法吗?因为我依靠正确的以前的状态来显示/隐藏某些内容。

  3. 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>
    

2 个答案:

答案 0 :(得分:11)

在github上打开的问题中有很多关于历史和导航的问题。

我猜导航已损坏,需要修复。

$ionicHistory跟踪推送堆栈上每个访问过的视图的视图。 实际上那里有2个阵列:

$ionicHistory.viewHistory().views

$ionicHistory.viewHistory().histories

我猜第一个是当前堆栈的历史记录,而第二个是所有历史记录 不同的导航可以有不同的历史记录:制表符,侧面菜单等等,当您从一个历史记录切换到另一个历史记录时,Ionic应记住每个状态。

通过他们的documentation阅读,您可以找到:

  

与传统的浏览器环境不同,应用程序和Web应用程序都有   并行独立历史,例如标签。应该是用户   在一个选项卡上深入导航几页,然后切换到新选项卡   返回,后退按钮不是与前一个选项卡相关,而是与之相关   在该标签中访问过的前几页。

您可以在此处找到 currentHistoryId $ionicHistory.currentHistoryId()

在进入主控制器的视图时,我已经更改了一些显示2个数组的示例:

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

如您所见,第一个数组视图会跟踪您访问过的所有视图。
如果你来回访问,如果你要显示之前访问过的视图,则不会添加元素。

每个视图都有两个属性: backViewId forwardViewId 。将元素添加到集合时,这两个值似乎是视图的一部分。导航时它们不会改变。

所以,当您按照顺序执行时会发生什么:

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

Ionic在集合中找到视图Fact2,得到它backViewId(指向Fact1),这就是它将用作返回视图的内容。

我没有在代码中进行一些调试,并尝试强制自己进行后视,但事情搞得一团糟。

我猜他们已经选择了这条路径,因为当你回到root - home时,应该隐藏后退按钮。 当您按照顺序执行操作时,事情无法正常工作:

我注意到的另一件事是,即使元素已经存在,有时会将视图添加到此集合中。

您可以尝试以下序列:

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

正如您现在所看到的,后退按钮(在标题中)告诉您后视图是Fact2,实际上控制台显示相同:

  • views:tabs.home
  • views:tabs.fact1
  • views:tabs.fact2
  • views:tabs.home
  • 历史记录堆栈:tabs.home
  • 历史记录堆栈:tabs.fact1
  • 历史记录堆栈:tabs.fact2
  • 历史记录堆栈:tabs.home

由于某些奇怪的原因,这次新的视图已添加到集合中,并且常规模式已更改。

这里有一个codepen进行了一些测试。

答案 1 :(得分:0)

我的解决方案/解决方法:

创建一个额外的状态来遍历,引用相同的url,templateUrl和controller。

例如,如果我有:

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

然后我还创建了一个只有不同州名

的“fact2”副本

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

如果我收到了有趣的过渡行为,我可以致电$state.go('fact2_duplicate'),历史将更符合我的预期。

希望这有助于某人。