当前位置: 首页 > 面试题库 >

手动转到先前状态时,$ ionicHistory.backView的状态不正确

赫连华皓
2023-03-14
问题内容

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

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

在每个状态变化,我在出console.log$ionicHistory.backView
但是,你可以在看pen.js:64线,奇怪的事情发生了。$ionicHistory.backViewapp.fact2从“后退”按钮获得的“思维”,它显示app.fact1为先前的状态(pen.js:53)。这是不对的,对吧?它应该显示app.fact3为以前的状态,因为我必须通过单击按钮来
手动*app.fact2状态。我还显示了(line )中的值,以防万一它很慢。但这仍然是不正确的。
*$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

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

$ionicHistory.viewHistory().views

$ionicHistory.viewHistory().histories

我猜第一个是当前堆栈视图的历史记录,第二个是所有历史记录。
不同的导航可能具有不同的历史记录:选项卡,菜单等,当您从一种历史记录切换到另一种历史记录时,Ionic应该记住每种状态。

阅读他们的文档,您会发现:

与传统的浏览器环境不同,应用程序和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);
        });
    });
})

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

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

因此,当您按照以下顺序进行时,会发生什么:

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

Ionic Fact2在集合中找到视图,得到它backViewId(指向Fact1),这就是将其用作视图的基础。

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

我想他们已经选择了此路径,当您回到根目录-主页-后退按钮应该被隐藏。遵循以下顺序时,事情将无法按预期进行:

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

您可以尝试以下顺序:

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

如您现在所见,后退按钮(位于标题中)告诉您后视图为Fact2,实际上控制台显示的内容相同:

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

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

这里有一些测试的codepen。



 类似资料:
  • 我引用了前台和后台接收firebase通知的答案-->https://stackoverflow.com/A/38451582/12553303 其实下面是我的疑问:-------- 如果我没有为前台条件编码(谈论推送通知),当我的应用程序在后台时,我仍然会得到通知,对吗????-->是的 但是,当im处于前台状态时,我从firebase推送了一个通知-->我不会在状态栏上看到通知,这也是可以的(

  • 我有一个类似这样的JSON对象, 我正在我的vue模板中循环使用这个来创建一个选择菜单, 通过将select绑定到data_type,每次我进行select更改时,它都会更新数据/json中该对象的数据。我想知道的是,是否可以在更改之前获取旧值? 我试着做了一些事情, 但是,新值和旧值似乎是相同的?

  • 问题内容: 是否有任何使用hibernate的公认的,行之有效的方式来保存实体在数据库中的更改历史? 我们需要跟踪相当多的对象,并且希望能够撤消对对象的更改。 我尝试使用hibernate模式的拦截器,但是对象的旧状态仅在执行时可用。大多数情况下我们还是这样做… 我目前正在让warp-persist和Guice一起管理会议。 问题答案: 我已经完成了一个拦截器(基于EmptyInterceptor

  • 问题内容: 从MDN for NodeList: 在某些情况下,NodeList是一个实时集合,这意味着DOM中的更改会反映在集合中。例如,Node.childNodes处于活动状态: 在其他情况下,NodeList是静态集合,这意味着DOM中的任何后续更改都不会影响集合的内容。document.querySelectorAll返回一个静态NodeList。 所以....有点烦!是否有任何关于哪些

  • 为了在重新创建活动后(例如在屏幕方向更改后)恢复活动的状态,我在SaveInstanceState()和onRestoreInstanceState()上实现了。保存/恢复int、double等简单信息很简单,但保存/恢复Timer等对象又如何呢?

  • 我在寻找一个逻辑结构的正确术语,我称之为“被动状态机”。 想象一下这个嵌入式设备:一些较低的程序层处理芯片读卡器,并通过确定三种状态对用户输入做出反应:“卡入”、“卡出”、“卡错”。在此执行足够的低级操作。称之为状态机。 下层向上层程序层报告状态,上层程序层对更改作出反应,并与系统的其余部分通信,即发送消息、开关、指示灯等。 这个上层的程序逻辑也可以建模(UML2),就像一个简化的状态机:它在状态