【问题标题】:Run a controller function whenever a view is opened/shown每当打开/显示视图时运行控制器功能
【发布时间】:2021-09-03 16:33:13
【问题描述】:

我正在使用 angular+ionic 构建一个应用程序,该应用程序在底部使用经典的三按钮菜单,其中包含三个离子选项卡。当用户单击选项卡时,该模板会通过 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()}} ?
  • 问题不在于 doSomething() 因为它启动得很好,只是它不会触发两次。视图第一次打开时运行良好,第二次似乎只是在加载缓存视图之类的?
  • ng-init 只调用该函数一次。您可以在局部视图中调用 ng-controller="doSomething()" 或 {{doSomething()}},并且每当调用 router/partial 时都会触发函数。
  • 在您的配置状态下,将您的缓存设置为 false。看看我的回答。

标签: angularjs ionic-framework


【解决方案1】:

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

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

更多阅读请访问http://ionicframework.com/docs/api/directive/ionNavView/

【讨论】:

  • 对注销控制器非常有用
  • 在 ionic 中默认开启缓存真的很不幸。似乎这应该是一个选择加入的功能,而不是默认添加它。
  • 我只需要重新加载一个状态,所以我使用了:$state.go('app.statename', {}, {reload:true});(more info, source)。
  • 虽然这可行,但它并不完全是正确的方法。它会减慢您的应用程序的速度 - 假设您不想每次用户切换到该视图时都经历整个控制器初始化过程,我认为 jczaplew 的答案是一个更好的方法。
  • 好东西。我禁用了整个应用程序的缓存。很高兴我遇到了这个答案
【解决方案2】:

跟进来自AlexMart 的答案和链接,类似这样的工作:

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

【讨论】:

  • $ionicView.beforeEnter 可能是你想要的。 $ionicView.enter 触发 after "the view has fully entered"。如果您使用动画视图转换,则使用$ionicView.beforeEnter 会在您的转换开始之前执行。这意味着您可以在期间运行您的代码,这可能会在您的应用中带来“更敏捷”的感觉。
  • 我认为这只是最简单和干净的答案。关于@rinogo 评论,我认为每个程序员都可以根据视图/控制器中发生的情况来决定是使用“enter”还是“beforeEnter”。这里要理解的重要一点是,您可以处理生命周期事件以在每次进入视图时调用函数。
【解决方案3】:

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

<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){ ... })

您可以在此处找到更多详细信息:State Change Events

【讨论】:

  • 谢谢,但这正是我正在做的。这段代码只会运行一次,第一次打开视图。我试图在我的控制台上记录一些东西,但它只在第一次触发。
  • 当你说它在你的应用程序中工作时,你是在谈论离子应用程序吗?我正在尝试看看它是否对我不起作用。
  • 使用 stateChange 可以解决问题,只需单击一个选项卡仍然只运行一次。感谢您的编辑!
  • 我认为这与 Ionic 缓存应用程序某些部分的方式有关。也许将 cache-view 设置为 false 会有所帮助吗? ionicframework.com/docs/api/directive/ionView 搜索缓存视图
  • 这可能是最近发布的 ionic 的问题。但是,您也可以在路由级别禁用缓存。只需在路由配置中为每个路由添加一个缓存:false。
【解决方案4】:

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

查看生命周期

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

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

【讨论】:

    【解决方案5】:

    为什么不使用 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。但是有一些情况是必要的。对我来说,我在视图上有一个插件绘图,但我不知道如何清理它。
    • 这对我来说是一个完美的解决方案,我正在注销用户然后再次访问控制器,我不想缓存,一切都应该重新初始化。谢谢!
    【解决方案6】:

    例如@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 -> 在显示视图之前运行。还有更多。

    【讨论】:

      【解决方案7】:

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

      $ionicConfigProvider.views.maxCache(0);

      否则,我让它为我工作的方式就是这样做

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

      这是在离开视图之前清除缓存以在每次您再次进入时重新运行控制器。

      【讨论】:

        【解决方案8】:

        这可能就是你要找的东西:

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

        您可以挂钩一些事件,让您的控制器根据这些离子事件执行某些操作。看这里的例子: http://ionicframework.com/blog/navigating-the-changes/

        【讨论】:

        • 可以通过显示示例代码而不是简单地共享链接来改进
        • Angular Js 上也有类似的东西吗?
        • @Wang'lPakhrin 默认情况下,您在主控制器函数中声明和运行的任何代码、IIFE 或函数将在每次加载视图(以及控制器)时执行。如果您需要在应用程序的生命周期中执行一次函数等事件,请查看 angular-ui-router 粘性状态和ViewContentLoadingViewContentLoaded 事件:)
        【解决方案9】:

        我在选择相机选项卡后尝试加载本机相机时遇到了类似的问题。我通过将控制器设置为相机选项卡的 ion-view 组件(在 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 方法都会加载本机相机。我确实没有必须更改角度缓存中的任何内容才能使其正常工作。我希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-07-12
          • 1970-01-01
          • 2022-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-13
          相关资源
          最近更新 更多