如何在 AngularJS 中的 Controller 之间正确共享和更新数据?

How to properly share and update data between Controllers in AngularJS?

所以我正在尝试使用 AngularJS 编码,而不是使用 $scope 或 $rootScope,而是命名控制器。

http://codepen.io/anon/pen/LpxOwx

这是 Angular 部分:

.controller('demoController', function(Fac){
  var vm = this;
  vm.theme = Fac.theme;
  vm.changeTheme = function(theme) {
    Fac.changeTheme(theme);
    vm.theme = Fac.theme;
  };
 })

.controller('secondController', function(Fac){
  var vm = this;
  vm.changeTheme = function(theme) {
    Fac.changeTheme(theme);
  };
 })

 .factory('Fac', function() {
  var fac = {
  theme: '',
  changeTheme: function(theme) {
    fac.theme = theme === 'indigo' ? 'lime' : 'indigo'; 
  }
}
return fac;
});

我分叉了一个代码笔来说明我的问题。 demoController 按预期工作并更新视图。但是在 secondController 中使用相同的 Factory 时它不会 "work"。我认为它可以工作,但不会在 demoController 中更新。

我理解 Angular 数据绑定的方式是,我需要做的就是使用工厂在绑定到它们的控制器之间共享数据,并根据变化进行相应更新。

我敢肯定,我在这里犯的是一个非常愚蠢的错误。我做错了什么?

更新:

感谢您的回答!不过,我遇到了一个新的(相关的?)问题:

http://plnkr.co/edit/cRa2FTkpbIsJ9TLzu5bD?p=preview

你能告诉我如何在 LoginCtrl 和 ToolbarCtrl 之间绑定用户,以便 ng-show 和 ng-hide 可以在登录和注销时更新吗?当我登录时,工具栏不会相应更新。我必须刷新整个页面而不是使登录可见。当我注销时它起作用了,因为我在 ToobarCtrl 中明确设置了 vm.user= {};

这是一个working version of your codepen

我只是使用了一个子变量来绑定到视图中。将原始变量从工厂绑定到控制器通常会导致这个麻烦之王。

工厂是这样的:

.factory('Fac', function() {
    var fac = {
      theme: {value:'indigo'},
      changeTheme: function(theme) {
        console.log(theme);
        fac.theme.value = theme === 'indigo' ? 'lime' : 'indigo'; 
      }
    }

两个控制器看起来像这样:

.controller('secondController', function(Fac){
      var vm = this;
      vm.theme = Fac.theme;
      vm.changeTheme = Fac.changeTheme;
  })

我在视图中这样使用它:

<md-button href="#" class="md-primary md-raised" ng-click=vm.changeTheme(vm.theme.value)>
  Change theme
</md-button>

希望对您有所帮助,

编辑: 在这里我解释了为什么这实际上不适用于原始变量

一种简单的方法是将工厂对象一直传递到视图:

.controller('demoController', function(Fac){
    var vm = this;
    vm.Fac= Fac;      
 });

然后在视图中使用对象的属性:

<md-button href="#" class="md-primary md-raised" ng-click=vm.Fac.changeTheme(vm.Fac.theme)>
  Change theme
</md-button>

Current theme is {{vm.Fac.theme}}

现在您没有将原语传递给子作用域并且控制器更精简了。

请注意,这不适用于工厂回调中可能需要某些控制器逻辑的所有情况,但在许多情况下,它可以避免重复创建可能并不真正需要的控制器属性。

您还可以对工厂对象进行分区,以尽量减少在可行的范围内重复相同的属性

DEMO