草庐IT

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

coder 2025-02-16 原文

我做了一个小实验: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 状态 MANUALLY。我还显示了 $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. 如何纠正这种行为?也许重写这个委托(delegate)或以某种方式覆盖它?

  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上打开的issues中有很多关于历史和导航的问题。

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

$ionicHistory 跟踪将每个访问过的 View 推送到堆栈上的 View 。 实际上那里有 2 个数组:

$ionicHistory.viewHistory().views

$ionicHistory.viewHistory().histories

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

阅读他们的 documentation你可以找到这个:

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

我已经稍微更改了您的示例,在进入主 Controller View 时显示 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);
        });
    });
})

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

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

所以,当您遵循以下顺序时会发生什么:

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

Ionic 在集合中找到 View Fact2,获取它的 backViewId(它指向 Fact1),这就是它将用作查看以返回。

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

我猜他们选择这条路是因为当你回到根目录 - 主页 - 后退按钮应该被隐藏。 当您按照以下顺序操作时,事情没有按预期进行:

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

你可以试试这个顺序:

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

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

  • View :tabs.home
  • View :tabs.fact1
  • View :tabs.fact2
  • View :tabs.home
  • 历史堆栈:tabs.home
  • 历史堆栈:tabs.fact1
  • 历史堆栈:tabs.fact2
  • 历史堆栈:tabs.home

由于某些奇怪的原因,这次在集合中添加了一个新 View ,并且常规模式发生了变化。

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

关于javascript - 手动转到上一个状态时 $ionicHistory.backView 的状态不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31364578/

有关javascript - 手动转到上一个状态时 $ionicHistory.backView 的状态不正确的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  4. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  5. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  6. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  7. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  8. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

随机推荐