2013-08-18 75 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

相關問題