angularjs:如何观察全局变量的变化?

angularjs:如何观察全局变量的变化?,angularjs,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="users

我想观看
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>
我用控制台试过:

myApp.myUser = {id:2, username:'jack'}
没什么。 然后,我尝试使用
tasksController

$scope.clickMe = function() {
    myApp.myUser = {id:2, username:'jack'}
}
我的观点没有改变

如的文档中所示,第一个参数必须是
监视表达式
——也就是说,一个角度表达式(一个
字符串
),描述应监视
$scope
中的值

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

请注意:

  • $watch
    如果你安装了很多手表,那么它可能会很贵。您通常希望为用户可以在视图上操作的数据设置一个监视,但不希望为通过代码直接加载的数据设置监视
  • 如果表达式指向一个对象,
    $watch
    将只跟踪对引用的更改,因此
    $scope.myUser={}
    将触发侦听器回调,但
    $scope.myUser.username='jack'不会。您可以传递第三个参数
    true
    ,使其检查深度不平等性,但对于复杂对象或大量手表,这会变得更加昂贵
如的文档中所示,第一个参数必须是一个
监视表达式
——即一个角度表达式(一个
字符串
),描述应监视
$scope
中的值

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

请注意:

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

我建议您通过在服务中将变量声明为

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'}
        }
    });

我建议您通过在服务中将变量声明为

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中存储数据有两个选项:

  • $rootScope
    -操作与
    $scope
    类似,但它连接到整个应用程序,而不仅仅是当前控制器
  • 。这是首选方法,因为它使代码模块化且可重用。在您的情况下,您可以设置一个数据服务
  • 那看起来像

    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);
    });
    
    myApp.factory('dataService',function()){
    变量用户=[
    {id:1,用户名:'john'}
    ];
    返回{
    getUser:函数(id){
    
    对于(i=0;i不要在
    myApp
    变量上使用属性,因为该变量实际上包含所有AngularJS功能,并且有发生冲突的风险

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

  • $rootScope
    -操作与
    $scope
    类似,但它连接到整个应用程序,而不仅仅是当前控制器
  • 。这是首选方法,因为它使代码模块化且可重用。在您的情况下,您可以设置数据服务
  • 那看起来像

    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);
    });
    
    myApp.factory('dataService',function()){
    变量用户=[
    {id:1,用户名:'john'}
    ];
    返回{
    getUser:函数(id){
    
    对于(i=0;i同意,但也希望敦促阅读此问答的任何人小心JS中的赋值操作。此示例使用
    $scope.myUser=userService.myUser
    行缓存引用,这是完全正确的,但前提是任何操作
    userService.myUser
    的代码都不会更改
    us的引用值erService.myUser
    (例如,
    userService.myUser={id:2,用户名:'jane'};
    )@Jessemano,你说得对。我用了一个简单的例子来说明这一点,但更好的解决方案是在
    return
    语句之前设置对象,然后返回getter和setter函数,以便引用保持完整。我在回答中添加了一条注释来说明这一点。是的!我之所以提出这个问题,主要是因为问题(以及迄今为止的一个答案)具有用新对象引用覆盖一个对象引用的代码,似乎期望只有旧引用的观察者会以某种方式观察新引用状态。同意。为了更好地解释,我再次更新了答案,因为考虑到问题的性质,我的简化版本可能会在ut澄清