ionicHistory美元.手动返回前一个状态时,backView的状态不正确

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

本文关键字:状态 一个 backView 不正确 美元 返回 ionicHistory      更新时间:2023-09-26

我做了一个小实验: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. 是否有解决方案?因为我依靠正确的先前的状态来显示/隐藏某些东西

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

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

我猜导航坏了,需要修复。

$ionicHistory跟踪每个被访问的视图在堆栈上的压入。实际上这里有两个数组:

$ionicHistory.viewHistory().views

$ionicHistory.viewHistory().histories

我猜第一个是当前堆栈的视图历史,而第二个考虑所有的历史。
不同的导航可以有不同的历史记录:选项卡、侧边菜单等等,当你从一个历史记录切换到另一个历史记录时,Ionic应该记住每个状态。

阅读他们的文档,你会发现这个:

与传统的浏览器环境不同,应用程序和web应用程序有并行独立的历史记录,如制表符。用户应该在一个标签上浏览几页深,然后切换到一个新的标签和后退,后退按钮与前一个选项卡无关,而是与

你可以在这里找到currentHistoryId: $ionicHistory.currentHistoryId() .

我已经改变了你的例子一点点显示两个数组时,进入主控制器的视图:

.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);
        });
    });
})
如你所见,第一个数组views记录了你访问过的所有视图。
如果你是在显示一个你之前访问过的视图,那么你就不会添加元素。

每个视图有两个属性:backViewIdforwardViewId。当元素被添加到集合中时,这两个值似乎是视图的一部分。它们不会随着你的导航而改变。

那么,当你遵循这个顺序时,会发生什么呢?

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

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

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

我猜他们选择了这个路径,因为当你回到根目录- home -后退按钮应该被隐藏。当您遵循以下顺序时,事情不会像预期的那样工作:

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

你可以试试这个顺序:

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

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

  • 视图:选项卡。家
  • 视图:选项卡。fact1
  • 视图:选项卡。fact2
  • 视图:tabs.home
  • 历史堆栈:选项卡。家
  • 历史堆栈:选项卡。fact1
  • 历史堆栈:选项卡。fact2
  • 历史堆栈:tabs.home

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

这里有一些测试。

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

创建一个额外的状态,以遍历到引用相同的url、templateUrl和控制器。

例如:

$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'),历史将更内联到我所期望的。

希望这能帮助到别人。

相关文章: