ionic和AngularJS:如何在导航之间保持状态?

时间:2014-07-17 06:54:46

标签: javascript angularjs ionic-framework

我正在开发我的第一款带有离子和AngularJS的混合移动应用程序,而这正是我想弄清楚的一件事:我们如何保持导航之间的状态(如GUI)?假设我的应用程序有一个包含这些项目链接的侧边菜单:

  1. 搜索表单
  2. 全部(#/all
  3. 猫(#/cats
  4. 狗(#/dogs
  5. 呃......奶牛? (#/cows
  6. 联络(#/contact
  7. 2到5的项目以inifite加载方式触发请求服务器数据。

    现在让我们说从 Cats ,我去 Dogs ,然后回到 Cats 。由于(根据我的理解),每次路由更改都会创建一个全新的Controller实例(和范围),应用程序将从服务器重新加载猫的列表。我希望保留 Cats 状态,然后重新显示。

    我一直在寻找一个解决方案(我认为应该足够普遍,只是我没有使用正确的搜索条件)。到目前为止,我发现的所有结果都建议您监听state changeroute change种事件,并将对象数组存储到localStorage中。虽然,对于某些扩展,这项工作,我觉得它是笨拙的,而不是做的方式 - 例如,HTML必须编译,这可能非常慢(注意我前面提到的“无限加载”功能,可以将对象数量增加到数百个,并且视口将恢复到应用程序的顶部。

    所以我的问题是,你们如何处理这个问题?是否有任何类似于浏览器后退和前进按钮的导航?

2 个答案:

答案 0 :(得分:1)

如果我理解你想要什么,你需要使用AngularJS服务。有关解释的详细信息,请参阅Ionic文档中的这篇文章:

http://learn.ionicframework.com/formulas/sharing-data-between-views/

在“与服务共享数据”部分中,您的问题的答案就在那里。

答案 1 :(得分:0)

我遇到了相反的问题,如果用户回到同一页面我想要刷新,但它不是。在过去10个月的某个时刻(在我提出这个问题和我写这篇文章之间),我相信Ionic实现了一个页面缓存,使他们的iOS幻灯片返回效果起作用。所以你的问题可能已经解决了,但以防万一...

通过添加" cache:false"修复了我的问题。到模块的.config()部分中的每个状态的选项。但是,在某些页面(或状态,我猜)我不希望它们重新加载,但是当用户回到它时我无法确定页面/状态是否仍然在缓存中。所以我决定在$ rootScope中设置一个标志...或者更确切地说,在$ rootScope中设置一个包含每个控制器的标志变量的对象,然后检查标志以查看该页面是否已被加载,并且如果是这样,请不要运行任何控制器代码。因此,对于您描述的设置,您将拥有以下内容:

app.js(或任何.js文件定义您的模块):

angular.module('MyApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('Search'  , { cache: true  , url:'/Search'  , templateUrl:'templates/Search.html'  , controller: 'SearchController'  })
    .state('All'     , { cache: true  , url:'/All'     , templateUrl:'templates/All.html'     , controller: 'AllController'     })
    .state('Dogs'    , { cache: true  , url:'/Dogs'    , templateUrl:'templates/Dogs.html'    , controller: 'CatsController'    })
    .state('Cows'    , { cache: true  , url:'/Cows'    , templateUrl:'templates/Cows.html'    , controller: 'DogsController'    })
    .state('Cats'    , { cache: true  , url:'/Cats'    , templateUrl:'templates/Cats.html'    , controller: 'CowsController'    })
    .state('Contact' , { cache: true  , url:'/Contact' , templateUrl:'templates/Contact.html' , controller: 'ContactController' });
  $urlRouterProvider.otherwise('/');
});

然后对于控制器,您可以这样做:

controllers.js

.controller('SearchController', function($scope, $rootScope, $state) {
    // If $rootScope.flags does not already exist, create it as an empty object
    $rootScope.flags = $rootScope.flags || {};

    if($rootScope.flags.SearchPageHasBeenOpenedAlready) {
      console.log("Search page was already opened, not doing anything.");
      return;
    } else {
      // Assuming this is the first controller, I guess you could initialize the flags here...
      // We will initialize them all to false and not set them to true until the code for
      // each controller has run through successfully
      $rootScope.flags.SearchPageHasBeenOpenedAlready  = false;
      $rootScope.flags.AllPageHasBeenOpenedAlready     = false;
      $rootScope.flags.CatsPageHasBeenOpenedAlready    = false;
      $rootScope.flags.DogsPageHasBeenOpenedAlready    = false;
      $rootScope.flags.CowsPageHasBeenOpenedAlready    = false;
      $rootScope.flags.ContactPageHasBeenOpenedAlready = false;
    }

    /* Whatever you normally do in SearchController goes here */

    $rootScope.flags.SearchPageHasBeenOpenedAlready = true;
  }
)

.controller('AllController', function($scope, $rootScope, $state) {
    // If $rootScope.flags does not already exist, create it as an empty object
    $rootScope.flags = $rootScope.flags || {};

    if($rootScope.flags.AllPageHasBeenOpenedAlready) {
      console.log("All page was already opened, not doing anything.");
      return;
    }

    /* Whatever you normally do in AllController goes here */

    $rootScope.flags.AllPageHasBeenOpenedAlready = true;
  }
)

/* 
And so forth until the last one...
*/

.controller('ContactController', function($scope, $rootScope, $state) {
    // If $rootScope.flags does not already exist, create it as an empty object
    $rootScope.flags = $rootScope.flags || {};

    if($rootScope.flags.ContactPageHasBeenOpenedAlready) {
      console.log("Contact page was already opened, not doing anything.");
      return;
    }

    /* Whatever you normally do in ContactController goes here */

    $rootScope.flags.ContactPageHasBeenOpenedAlready = true;
  }
);