每当打开/显示视图时运行控制器功能


81

我正在构建一个带有angular + ionic的应用程序,该应用程序在底部使用一个经典的三按钮菜单,其中包含三个ion-tabs。用户单击选项卡时,该模板通过ui-router打开。

我有这样的状态:

$stateProvider
  .state('other', {
    url: "/other",
    abstract: true,
    templateUrl: "templates/other/other.html"
})

在模板中,我执行以下操作:

<ion-nav-view name="other" ng-init="doSomething()"></ion-nav-view>

我知道我可以在控制器中编写doSomething()函数,并在那里手动调用它。那给了我同样的问题。每当有人打开该视图时,我似乎都无法弄清楚如何调用doSomething()函数。

现在,可以很好地调用doSomething()函数,但是仅在用户第一次打开视图/选项卡时才可以。每当用户打开该视图或标签时,我都想调用一个函数(以更新地理位置)。

什么是实现该目标的正确方法?

感谢您的帮助!


尝试{{doSomething()}}吗?
Asik 2014年

1
问题不在于doSomething(),因为它启动得很好,只是它不会触发两次。第一次打开视图时,它运行良好,第二次似乎只是在加载缓存的视图或其他内容?
Jorre 2014年

ng-init仅调用一次函数。您可以在局部视图中调用ng-controller =“ doSomething()”或{{doSomething()}},每当路由器/局部调用时函数就会被触发。
阿西克

3
在配置状态下,将缓存设置为false。看看我的答案。
Yakob Ubaidi

Answers:


46

如果已为视图分配了某个控制器,则每次加载视图时都会调用该控制器。在这种情况下,您可以在调用控制器后立即执行一些代码,例如,通过这种方式:

<ion-nav-view ng-controller="indexController" name="other" ng-init="doSomething()"></ion-nav-view>

在您的控制器中:

app.controller('indexController', function($scope) {
    /*
        Write some code directly over here without any function,
        and it will be executed every time your view loads.
        Something like this:
    */
    $scope.xyz = 1;
});

编辑:您可能会尝试跟踪状态更改,然后在更改路线并访问特定路线时执行一些代码,例如:

$rootScope.$on('$stateChangeSuccess', 
function(event, toState, toParams, fromState, fromParams){ ... })

您可以在此处找到更多详细信息:状态更改事件


6
谢谢,但这正是我正在做的。该代码仅在视图首次开放时运行一次。我试图将某些内容记录到控制台,但它仅在第一次触发。
Jorre 2014年

当您说它适用于您的应用程序时,您是否也在谈论离子应用程序?我正在尝试查看是否对我不起作用。
Jorre 2014年

2
使用stateChange可以解决问题,仅单击选项卡仍然只运行一次。感谢您的编辑!
Jorre 2014年

我认为这与Ionic缓存应用程序某些部分的方式有关。也许设置cache-view为false会有所帮助吗?ionicframework.com/docs/api/directive/ionView搜索缓存视图
Michael Trouw

这可能是最近释放的离子的问题。但是,您也可以在路由级别禁用缓存。只需为您的路由配置中的每条路由添加一个缓存:false。
Manish Kr。Shukla 2015年

88

默认情况下,控制器是缓存的,这就是为什么控制器仅触发一次的原因。要关闭某个控制器的缓存,您必须修改.config(..).state并将其设置cachefalse。例如:

  .state('myApp', {
    cache: false,
    url: "/form",
    views: {
      'menuContent': {
        templateUrl: "templates/form.html",
        controller: 'formCtrl'
      }
    }
  })

欲了解更多信息,请访问http://ionicframework.com/docs/api/directive/ionNavView/


2
对于注销控制器非常有用
mrwaim 2015年

3
不幸的是,在ionic中默认情况下已启用缓存。似乎这应该是一种选择加入功能,而不是默认添加它。
oalbrecht

我只需要重新加载一个状态,所以我用:$state.go('app.statename', {}, {reload:true});更多信息)。
Sjoerd Pottuit

1
尽管这行得通,但这并不是正确的解决方法。这将减慢您的应用程序运行速度-假设您不想每次用户切换到该视图时都通过整个控制器初始化过程,我认为jczaplew的答案是一种更好的方法。
克里斯·雷

好东西。我禁用了整个应用程序的缓存。很高兴我遇到了这个答案
Robert Ngetich

50

跟踪来自AlexMart的答案和链接,类似的方法有效:

.controller('MyCtrl', function($scope) {
  $scope.$on('$ionicView.enter', function() {
     // Code you want executed every time view is opened
     console.log('Opened!')
  })
})

3
$ionicView.beforeEnter可能就是您想要的。 在“视图已完全进入”后$ionicView.enter触发。如果您正在使用动画视图过渡,请过渡开始之前使用executes 。这意味着您可以过渡期间运行代码这可能会导致您的应用程序具有“快照”的感觉。$ionicView.beforeEnter
rinogo

我认为这只是最简单和干净的答案。关于@rinogo注释,我认为每个程序员都可以根据视图/控制器中发生的任何事情来决定使用“ enter”还是“ beforeEnter”。这里要了解的重要一点是,您可以处理生命周期事件,每次进入视图时就调用一个函数。
jcarballo

12

我遇到了同样的问题,在这里,我将这种行为的原因留给其他有同样问题的人。

查看生命周期

为了提高性能,我们提高了Ionic缓存视图元素和范围数据的能力。控制器初始化后,可能会在应用程序的整个生命周期中持续存在;它只是隐藏并从手表周期中删除。由于我们没有重建作用域,因此我们添加了一些事件,在再次进入监视周期时应监听这些事件。

要查看完整的描述和$ ionicView事件,请访问:http ://ionicframework.com/blog/navigating-the-changes/


9

为什么不使用cache-view =“ false”禁用视图缓存?

在您的视图中,将其添加到ion-nav-view中,如下所示:

<ion-nav-view name="other" cache-view="false"></ion-nav-view>

或在您的stateProvider中:

$stateProvider.state('other', {
   cache: false,
   url : '/other',
   templateUrl : 'templates/other/other.html'
})

任一种都会使您的控制器始终被调用。


这会对性能产生副作用吗?我以为该视图已缓存,因此不会每次都重新加载整个视图。禁用此功能不会导致整个页面再次加载,而我们只希望再次执行一段代码?
Sindarus '16

大概是@Sindarus。但是有一些情况是必要的。对我来说,我在视图上有一个插件绘图,但我不知道该如何清洁它。
Diogo Medeiros

对于我的情况而言,这是一个完美的解决方案,我先注销用户,然后再次访问控制器,我不想缓存,并且应该重新初始化所有内容。谢谢!
Firas Abd Alrahman

5

例如@Michael Trouw,

在您的控制器内部放置此代码。该命令将在每次进入或激活此状态时运行,您无需担心禁用缓存,这是一种更好的方法。

.controller('exampleCtrl',function($scope){
$scope.$on('$ionicView.enter', function(){
        // Any thing you can think of
        alert("This function just ran away");   
    });
})

您可以有更多的灵活性示例,例如$ ionicView.beforeEnter->在显示视图之前运行。还有更多。


2

考虑到Ionic缓存上述视图元素和范围数据的能力,如果您希望每次加载视图时都运行控制器,则这可能是另一种方法。您可以执行以下操作全局禁用ionic使用的缓存机制:

$ionicConfigProvider.views.maxCache(0);

否则,我为我工作的方式是

$scope.$on("$ionicView.afterLeave", function () {
     $ionicHistory.clearCache();
}); 

这样做是为了在每次再次输入返回视图前都重新运行控制器之前清除缓存。


1

这可能是您想要的:

Ionic会默认缓存您的视图,从而默认缓存您的控制器(最多10个) http://ionicframework.com/docs/api/directive/ionView/

您可以关联一些事件,以使控制器根据这些离子事件执行某些操作。参见此处的示例:http : //ionicframework.com/blog/navigating-the-changes/


1
可以通过显示示例代码而不是简单地共享链接来进行改进
Lawrence Weru 2015年

Angular Js上也有类似的东西吗?
Wang'l Pakhrin

@ Wang'lPakhrin默认情况下,每次加载视图(并因此加载控制器)时,都将执行在主控制器功能中声明并运行的任何代码,IIFE或函数。如果您需要在应用程序的生命周期中执行一次函数之类的事件,请查看angular-ui-router粘性状态ViewContentLoadingViewContentLoaded事件:)
Michael Trouw

0

我在ionic上也遇到了类似的问题,在我选择“相机”选项卡后,我试图加载本机相机。通过将控制器设置为“相机”选项卡的离子视图组件(在tabs.html中),然后调用加载我的相机的$ scope方法(addImage),我解决了该问题。

在www / templates / tabs.html中

  <ion-tab title="Camera" icon-off="ion-camera" icon-on="ion-camera" href="#/tab/chats" ng-controller="AddMediaCtrl" ng-click="addImage()">
    <ion-nav-view  name="tab-chats"></ion-nav-view>
  </ion-tab>

每次用户单击“摄像机”选项卡时,在AddMediaCtrl中定义的addImage方法都会加载本机摄像机。我不必更改角度缓存中的任何内容即可工作。我希望这有帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.