动态更改控制器 $scope 变量

Changing controller $scope vars dynamically

所以。我有简单的控制器和服务:

angular
    .module('field', [])
    .controller('FieldController', function(FieldService) {
         var vm = this;
         vm.name = FieldService.getName();
    })
    .service('FieldService', function() {
         var name = 'John'
         this.getName = function() {
             return name;
         };
         this.setName = function(newName) {
             name = newName;
         };
    })
    ;

然后我在 anotherService 中有一些 $interval,每 1 秒获取一次数据并调用 FieldService.setName:

    .service('UpdateService', function($http, FieldService) {
        $interval(function() {
            $http.get('/somUrl')
                .then(function(response) {
                    FieldService.setName(response.name);
                });
        });
    })

但这不会改变我的 HTML。 如果我在返回值 getName 中从原始对象切换到对象,那么它正在工作。

还有其他方法吗?我个人认为,我创建的这个结构很糟糕,但无法理解应该如何完成。

我会将我的 $interval 函数移到控制器中,然后每秒更新一个 $scope 属性。然后 Angular 将负责渲染。或者您还必须在控制器中使用 $interval 函数,它每秒获取服务内容(即 FieldService.getName)。

JavaScript 始终是按值传递,但是当您的变量是对象时,'value' 实际上是对该对象的引用。所以在你的例子中,你得到的是对象的引用,而不是值。因此,当对象发生变化时,该变化不会像基元那样传播。

您的代码似乎也有点不正确。您正在将 response.name 的值设置为 FieldService.setName,这实际上是一个函数。

如果您想使用您列出的 getter/setter 方法,那么您可以使用事件让控制器知道名称已更改。

.service('UpdateService', function($http, FieldService, $rootScope) {
        $interval(function() {
            $http.get('/somUrl')
                .then(function(response) {
                    FieldService.setName(response.name);
                    $rootScope.$broadcast('nameChanged', {
                        name : response.name
                    });
                });
        });
    })

  .controller('FieldController', function(FieldService, $scope) {
         var vm = this;
         vm.name = FieldService.getName();

         $scope.$on('nameChanged', function (evt, params) {
             vm.name = params.name;
         });
    })

实现此目的的另一种方法是在控制器中的服务变量上使用 $scope.$watch

.controller('FieldController', function($scope, FieldService) {
         $scope.name = FieldService.getName();
         $scope.$watch(function () {
            return FieldService.getName();
         }, function (newVal, oldVal) {
            if (newVal !== oldVal) {
                $scope.name = newVal;
            }            
         });
    })

我会这样使用它:

angular
    .module('field', [])
    .controller('FieldController', function($scope, FieldService) {
         $scope.name = function(){
            FieldService.getName();
         };
    })
    .service('FieldService', function() {
         var name = 'John'
         this.getName = function() {
             return name;
         };
         this.setName = function(newName) {
             name = newName;
         };
    });

在您的 html 中使用 name() 来查看更新值。
以及您的其他服务:

.service('UpdateService', function($http, FieldService) {
        $interval(function() {
            $http.get('/somUrl')
                .then(function(response) {
                    FieldService.setName(response.name);
                });
        }, 1000);
    })

您可以通过多种方式实现这一目标。没有办法就是最好的办法。因人而异。

希望对您有所帮助。

有几种方法可以解决这个问题。

1) 将 $interval 移动到控制器。然后你将有一个变量,它保存该数据,你可以在视图中绑定它

2) 您可以使用 AngularJs 事件。$rootScope 将帮助您发送信号并在任何您想要的地方捕获它。

如果您想了解有关此解决方案的更多信息,可以在此处查看: http://www.w3docs.com/snippets/angularjs/bind-value-between-service-and-controller-directive.html