$ionicHistory.backView 手动进入前一状态时状态不正确 [英] $ionicHistory.backView has incorrect state when go to previous state manually

查看:16
本文介绍了$ionicHistory.backView 手动进入前一状态时状态不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这是我的状态流(点击按钮):Home ->事实 1 ->事实 2 ->事实 3 ->事实2

Here is my state flow (click on the buttons): 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 状态 MANUALLY.我还显示了来自 $timeout(行 pen.js:59)的值,以防万一它很慢.但它仍然是不正确的.

On each state change, I am showing in console.log for $ionicHistory.backView However, you can see in pen.js:64 line, weird things happen. The $ionicHistory.backView "thinks" that I got to app.fact2 from a back button, and it shows app.fact1 as the previous state (line pen.js:53). This is incorrect, right? It should show app.fact3 as the previous state because I got to app.fact2 state MANUALLY by clicking the button. I also showed the value from $timeout (line pen.js:59) just in case it's slow. But it's still 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

问题

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

  1. How to correct this behavior? Maybe rewrite this delegate or override it somehow?

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

Is there a workaround? As I rely on the correct previous state in order to show/hide something.

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>

推荐答案

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

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 跟踪将每个访问过的视图推送到堆栈上的视图.实际上那里有 2 个数组:

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

$ionicHistory.viewHistory().views

$ionicHistory.viewHistory().histories

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

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.

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

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

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

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

如您所见,第一个数组 views 会跟踪您访问过的所有视图.
如果您正在显示您之前访问过的视图,则如果您来回切换不会添加元素.

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.

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

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 在集合中找到视图 Fact2,获取它的 backViewId(指向 Fact1),这就是它将用作查看返回.

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.

你可以试试这个顺序:

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

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

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:

  • 视图:tabs.home
  • 视图:tabs.fact1
  • 视图:tabs.fact2
  • 视图:tabs.home
  • 历史堆栈:tabs.home
  • 历史堆栈:tabs.fact1
  • 历史堆栈:tabs.fact2
  • 历史堆栈:tabs.home

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

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

这里有一个 codepen 有一些测试.

There's a codepen here with some tests.

这篇关于$ionicHistory.backView 手动进入前一状态时状态不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆