发布绑定/观察两个控制器之间共享的服务变量

时间:2013-08-18 15:08:11

标签: javascript angularjs angularjs-scope angularjs-service

我很难解读这里发生的事情。我理解Angular的$摘要周期的基础知识,并且根据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');
        }
    });
})

})();

2 个答案:

答案 0 :(得分:4)

您的代码存在两个问题:

  1. 数组没有count属性;你应该使用length代替。

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

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

    < / LI>
  2. setThings TestService方法用things替换TestService.things数组的引用,使CtrlA.$scope.things指向内存中的新数组CtrlB.$scope.thingsvar 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); }); 数组的方式。这是一个建议:

    {{1}}

    }

  3. 这是你的jsFiddle的working version

答案 1 :(得分: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,它只是简单地获取你服务中的属性,然后我看了这个函数(AFAIK $ watch对参数做了一个eval,所以你可以看函数),深入检查(真正的参数)在末尾)。你的另一个控制器也一样。然后,当您修改服务的价值时,两个$观察者会看到它,并且数据正确绑定

实际上,我不知道这是不是最好的方法,但它似乎适用于你的例子,所以我认为你可以这样看待

玩得开心:)