2013-08-18 43 views
2

我很难破译这里发生的事情。我理解Angular的$ digest循环的基础知识,根据this SO post,我通过简单地将一个有作用域的var分配给一个服务的属性(在这种情况下是一个数组)来正确地做事。正如你所看到的,我可以让CtrlA的'东西'更新的唯一方法是在我更新我的服务的属性并引用一个新数组后,重新分配它。在两个控制器之间共享/监视服务变量的问题

这里是说明我的问题一个小提琴:

http://jsfiddle.net/tehsuck/Mujun/

(function() { 
angular.module('testApp', []) 
    .factory('TestService', function ($http) { 
    var service = { 
     things: [], 
     setThings: function (newThings) { 
      service.things = newThings; 
     } 
    }; 
    return service; 
}) 
    .controller('CtrlA', function ($scope, $timeout, TestService) { 
    $scope.things = TestService.things; 
    $scope.$watch('things.length', function (n, o) { 
     if (n !== o) { 

      alert('Things have changed in CtrlA'); 
     } 
    }); 
    $timeout(function() { 
     TestService.setThings(['a', 'b', 'c']); 

     // Without the next line, CtrlA acts like CtrlB in that 
     // it's $scope.things doesn't receive an update 
     $scope.things = TestService.things; 
    }, 2000); 
}) 
    .controller('CtrlB', function ($scope, TestService) { 
    $scope.things = TestService.things; 
    $scope.$watch('things.length', function (n, o) { 
     if (n !== o) { 
      // never alerts 
      alert('Things have changed in CtrlB'); 
     } 
    }); 
}) 

})();

回答

4

有两个问题与您的代码:

  1. 数组没有count财产;您应该使用length

    $scope.$watch('things.length', ...); 
    

    但有一点需要注意:如果添加,并从things数组中删除元素/并用不同的列表相同长度则观察者回调将不会触发结束。

  2. TestServicesetThings方法代替参考things阵列用一个新的,使得TestService.things点到一个新的数组中的存储器中,同时既CtrlA.$scope.thingsCtrlB.$scope.things保持指向旧阵列,它是空的。下面的代码说明:

    var a = []; 
    var b = a; 
    
    a = [1, 2, 3]; 
    console.log(a); // prints [1, 2, 3]; 
    console.log(b); // prints []; 
    

    因此,为了使你的代码工作,你需要改变TestService.setThings更新其things阵列的方式。这里有一个建议:

    setThings: function (newThings) { 
        service.things.length = 0; // empties the array 
        newThings.forEach(function(thing) { 
         service.things.push(thing); 
        });     
    

    }

而且,这里是你的jsfiddle的working version

+0

:咔咔咔咔:好吧,我把Array.count的事情归结为试图快速写出这个AM。抱歉。 – Chief

+0

我明白你对数组引用的看法,我想这就是我不明白的地方。我理解它的方式,在$摘要期间,我认为如果数据绑定是Object或Array,angular会比较引用?我想我错了。 虽然谢谢! – Chief

+0

这不是一个角度问题。当你将'TestService.things'指向另一个数组时,'CtrlA。$ scope.things'仍然指向空的旧的,并且Angular会相应地渲染它。据Angular所知,“CtrlA。$ scope.things”没有任何改变。 –

1

我真的不知道为什么,但如果您使用函数来返回服务中的数据,然后您观看该函数而不是属性,它似乎会得到更正。因为它似乎不清楚,你可以在这里看到:http://jsfiddle.net/DotDotDot/Mujun/10/
我加在你的服务一个getter:

var service = { 
     things: [], 
     setThings: function (newThings) { 
      service.things = newThings; 
     }, 
     getThings:function(){ 
      return service.things; 
     } 
    }; 

然后,我修改了两个控制器代码本:

$scope.things = TestService.getThings(); 
    $scope.getThings=function(){return TestService.getThings();}; 
    $scope.$watch('getThings()', function (n, o) { 
     if (n !== o) { 
      // never alerts 
      alert('Things have changed in CtrlA'); 
     } 
    }, true); 

,并在HTML:

<li ng-repeat="thing in getThings()">{{thing}}</li> 

它定义了一个函数getThings,它将简单地获取您的服务中的属性,然后我看着这个函数n(AFAIK $手表对参数进行评估,以便您可以观看功能),并进行深度检查(最后的真实参数)。在你的其他控制器中是一样的。然后,当你修改你的服务的价值时,它被两个$观察者看到,并且数据被正确绑定

其实,我不知道它是否是最好的方法,但它似乎与你的例如,所以我觉得你可以看看这样

玩得开心:)

+0

谢谢@DotDotDot – Chief

相关问题