控制器切换后匿名功能中的访问服务数据发生变化

Access service data changed in anonymous function after controller switch

本文关键字:服务 访问 数据 变化 功能 控制器      更新时间:2023-09-26

我简化了我的实际代码,但问题是相同的。单击"第一个控制器"中的匿名功能后Start counter开始更改myService中的数据。首先它工作正常。但是切换到"第二个控制器"后,即使您导航回"第一个控制器",Angular 也会停止自动更新<span ng-bind="getData().data">值。

但是,如果您来回切换控制器,您可以看到跨度在控制器负载时更新,因此数据正在更改,控制器可以访问它。只是 Angular 不再自动跟踪它了。

如何使 Angular 在再次切换控制器后开始跟踪更改和更新元素?

<html>
<head>
<script src="https://code.angularjs.org/1.4.0-beta.4/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-beta.4/angular-route.min.js"></script>
</head>
<body>
<div style="padding: 0 0 20px 0">
    <a href="#/first">First controller</a> | <a href="#/second">Second controller</a>
</div>
<div ng-app="myApp">
    <div ng-view></div>
    <script type="text/ng-template" id="temp1.html">
        Data: <span ng-bind="getData().data"></span>
        <br/>
        <button ng-click="start()">Start counter</button>
    </script>
    <script type="text/ng-template" id="temp2.html">
        Data: <span ng-bind="getData().data"></span>
    </script>
</div>  
<script type="text/javascript">
    var myControllers = angular.module('myControllers', []);
    myControllers.factory('myService', [function() {
        return { data: 0 };
    }]);
    myControllers.controller('myController1', ['$scope', 'myService', function($scope, myService){
        $scope.getData = function() {
            return myService;
        }
        $scope.start = function() {
            setInterval(function() {
                myService.data++;
                $scope.$apply();    
            }, 1000)
        }
    }]);
    myControllers.controller('myController2', ['$scope', 'myService', function($scope, myService){
        $scope.getData = function() {
            return myService;
        }
    }]);
    var myApp = angular.module('myApp', [
      'ngRoute',
      'myControllers'
    ]);
    myApp.config(['$routeProvider',function($routeProvider) {
        $routeProvider.
            when("/first",{ controller: "myController1", templateUrl: "temp1.html"}).
            when("/second", {controller: "myController2", templateUrl: "temp2.html"}).
            otherwise({redirectTo : "/first"});
    }]);
</script>
</body>
</html>
所以我

实际上在这里找到了一个答案:使用服务在控制器之间传递数据,并使用['$scope', 'service' , function($scope, service){}]混淆(参见Anthony Chu Feb 17 '14 at 6:12的评论)。诀窍在于使用 $rootController 通过事件向所有其他控制器发出警报,以更新服务中的数据。因此,匿名函数将在后台运行,而无需引用新$scope但新$scope将通过$rootScope事件向下传播从它接收消息。

我已将$root.$broadcast(...)附加到匿名函数,并将各自的$scope.$on(...)附加到两个控制器。因此,控制器代码现在如下所示:

myControllers.controller('myController1', ['$scope', 'myService', '$interval', '$rootScope', 
  function($scope, myService, $interval, $rootScope) {
    $scope.getData = function() {
      return myService;
    }
    $scope.$on('myupdate', function() {
      if (!$scope.$$phase) { //checks that Angular is not updating scope right now
        $scope.$apply();
      }        
    });
    $scope.start = function() {
      setInterval(function() {
        myService.data++;
        $rootScope.$broadcast('myupdate');
      }, 1000)
    }
}]);
myControllers.controller('myController2', ['$scope', 'myService',
  function($scope, myService) {
    $scope.getData = function() {
      return myService;
    }
    $scope.$on('myupdate', function() {
      if (!$scope.$$phase) {
        $scope.$apply();
      }        
    });
}]);

完全工作的代码示例。