Angularjs:如何观察全局变量的变化



我想看看myApp.myUser的变化:

<html ng-app="myApp">
<head>
<script src="js/vendor/angular/angular.min.js"></script>
  <script src="js/app2.js"></script>
</head>
<body>
    <div id="users" ng-controller="usersController">
    <h4>usersController</h4>
    test = {{myUser}}
    </div>        
    <div id="tasks" ng-controller="tasksController">
    <button ng-click="clickMe()">cliquez ici </button>
    </div>
</body>
</html>

和app2.js:

var myApp = angular.module('myApp', []);
myApp.users = {};
myApp.tasks = {};
myApp.myUser = {id:1, username:'john'}
myApp.controller('usersController', function($scope) {
    $scope.myUser = myApp.myUser;
    $scope.$watch(myApp.myUser, $scope.userChanged);
    $scope.userChanged = function() {
        console.log('userChanged');
    }   
});
myApp.controller('tasksController', function($scope) {
    $scope.tasks = myApp.tasks;
    $scope.clickMe = function() {
        myApp.myUser = {id:2, username:'jack'}
    }
});

我用console试过了:

myApp.myUser = {id:2, username:'jack'}

。然后我尝试通过AngularJS通过tasksController

$scope.clickMe = function() {
    myApp.myUser = {id:2, username:'jack'}
}

我的观点没有改变!

http://jsfiddle.net/halirgb/Lvc0u55v/

我建议您通过在服务中声明

来使用这些变量
var myApp = angular.module('myApp', []);
    myApp.factory('DataService',function(){
      var myUser ={id:1, username:'john'};
      var tasks;
      var users;
      return{
      users:users,
      tasks:tasks,
      myUser:myUser
      }
    });
    myApp.controller('usersController', function($scope,DataService) {
        $scope.myUser = DataService.myUser;
        console.log(DataService.myUser);   
       $scope.$watch(DataService.myUser, $scope.userChanged);
        $scope.userChanged = function() {
            console.log('userChanged');
        }   
    });
    myApp.controller('tasksController', function($scope,DataService) {
        $scope.tasks = DataService.tasks;
        $scope.clickMe = function() {
            DataService.myUser = {id:2, username:'jack'}
        }
    });

不要在你的myApp变量上使用属性,它实际上包含了AngularJS的所有功能,你可能会有冲突的风险。

在AngularJS中有两个存储数据的选项:

  1. $rootScope -操作就像$scope,但附加到整个应用程序,而不仅仅是当前控制器。
  2. 服务。这是首选的方法,因为它使代码保持模块化和可重用性。在您的例子中,您可以设置一个数据服务。

它看起来像…

myApp.factory('dataService', function() {
    // this is simplified for illustration, see edit below
    return {
        myUser: {id: 1, username: 'john'},
    };
});
myApp.controller('usersController', function($scope, dataService) {
    $scope.myUser = dataService.myUser;
});

编辑:

正如在评论中讨论的那样,这带来了另一个潜在的绑定问题,因为我使用了一个可以通过userService.myUser = {};覆盖的文字值。提供更可靠的双向绑定的更好的数据服务应该是这样的:

myApp.factory('dataService', function() {
    var users = [
        { id: 1, username: 'john' }
    ];
    return {
        getUser: function(id) {
            for (i=0; i<users.length; i++) {
                if (users[i].id === id) {
                    return users[i];
                }
            }
        }
    };
});
myApp.controller('usersController', function($scope, dataService) {
    $scope.myUser = dataService.getUser(1);
});

如文档中$scope所示。$watch的第一个参数必须是一个watchExpression——也就是说,一个Angular表达式(一个string),它描述了$scope中的哪个值应该被监视。

您的值myApp.myUser不是$scope的一部分,$watch无法到达。解决方案是将对象移动到$scope.myUser之类的地方,然后调用$scope.$watch('myUser', function() { console.log('userChanged'); });

注意:

    如果你设置了很多手表,$watch可能会很昂贵。你通常希望为用户可以在视图上操作的数据设置一个watch,而不是为直接通过代码加载的数据设置watch。
  • 如果表达式指向一个对象,$watch将只跟踪对引用的更改,因此$scope.myUser = {};将触发侦听器回调,但$scope.myUser.username = 'jack';不会。你可以传递第三个参数true来检查深度不平等,但对于复杂的对象或大量的手表,这将变得更加昂贵。